danyspin97 / wpaperd

Modern wallpaper daemon for Wayland
GNU General Public License v3.0
332 stars 26 forks source link

Long delay after before image is rendered #49

Closed tbaumann closed 9 months ago

tbaumann commented 1 year ago

I notice a long delay before the image is rendered. This happens at startup or after a wpaperctl next-wallpaper command

Most of the delay is between the first and second mmap in the strace output.

rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
futex(0x7f886d22bd1c, FUTEX_WAIT_BITSET_PRIVATE, 0, NULL, FUTEX_BITSET_MATCH_ANY) = 0
close(13)                               = 0
write(2, "INFO [wpaperd::surface] New imag"..., 100INFO [wpaperd::surface] New image for monitor "DP-3": "/home/tilli/wallpapers/wallhaven-yxk8xg.jpg"
) = 100
mmap(NULL, 108290048, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f87898ba000
mmap(NULL, 58478592, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f879483b000
munmap(0x7f87898ba000, 108290048)       = 0
mmap(NULL, 44240896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f87b45c7000
munmap(0x7f879483b000, 58478592)        = 0
mmap(NULL, 58986496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f87947bf000
munmap(0x7f87b45c7000, 44240896)        = 0
munmap(0x7f87947bf000, 58986496)        = 0
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\f\0\0\0\0\0 \0\v\0\0\0\0\0\0\0\0\24\0\0@\v\0\0\0P\0\0AB24"..., iov_len=92}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 92
timerfd_settime(6, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=3583, tv_nsec=745757536}}, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=3583, tv_nsec=745953330}}) = 0
epoll_ctl(4, EPOLL_CTL_MOD, 6, {events=EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLONESHOT, data={u32=4294967295, u64=18446744073709551615}}) = 0
epoll_wait(4, [{events=EPOLLIN, data={u32=1, u64=1}}], 1024, -1) = 1
read(5, 0x7ffceffa1a10, 8)              = -1 EAGAIN (Resource temporarily unavailable)
epoll_ctl(4, EPOLL_CTL_MOD, 5, {events=EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLONESHOT, data={u32=4294967295, u64=18446744073709551615}}) = 0
recvmsg(3, {msg_name=0x7ffceffa1b90, msg_namelen=0 => 27, msg_iov=[{iov_base="\v\0\0\0\0\0\10\0\1\0\0\0\1\0\f\0\v\0\0\0", iov_len=8192}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) = 20
recvmsg(3, {msg_namelen=0}, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x5600462622e0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
timerfd_settime(6, 0, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=3583, tv_nsec=705479810}}, {it_interval={tv_sec=0, tv_nsec=0}, it_value={tv_sec=3583, tv_nsec=705490971}}) = 0
epoll_ctl(4, EPOLL_CTL_MOD, 6, {events=EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLONESHOT, data={u32=4294967295, u64=18446744073709551615}}) = 0
tbaumann commented 1 year ago

Nothing interesting to add with RUST_LOG=debug wpaperd -n -v

danyspin97 commented 1 year ago

Hello @tbaumann and thanks for the report. The image rendering is pretty slow when building wpaperd in debug mode. Does this occur with a release build as well?

tbaumann commented 1 year ago

Ah you are right. I first noticed the issue in debug mode. I noticed it got faster, but I didn't realize it's because I was using release builds now.

The delay is still in the multiple seconds range. But not so extreme anymore.

danyspin97 commented 1 year ago

What are your screen resolution and the images' resolution?

tbaumann commented 1 year ago

The images vary widely. They are full resolution downloads from wallhaven. Between 1920x1200 and 3285x1080. So rather large actually. If the delay correlates to the image size I have a good explanation why the delay is not always the same. Sometimes multiple seconds sometimes a lot less.

Screen is 3840x2160

I guess knowing that it's not some dumb socket timeout or anything like that I'm satisfied. I just suspected it would be a bug. The CLI interface is locked while it renders, but not in a breaking kind of way. So it's fine.

But of course it's a pretty bad rendering speed in any case. But I guess that's probably mostly happening in 3rd party libs anyway?

Either way, close if you like.

tbaumann commented 1 year ago

PS: I was thinking of opening another bug. But I throw this out here. wpaperctl get-wallpaper should perhaps work without arguments and default as in the config should be a valid monitor name. I'm not sure if that makes sense with how it works internally. And there is all-wallpapers. But the other commands work without aguments too

danyspin97 commented 1 year ago

But of course it's a pretty bad rendering speed in any case. But I guess that's probably mostly happening in 3rd party libs anyway?

You're almost correct, it is related to the image size. By default, wpaperd draws a window of the size of the screen and upscale the wallpaper to match. The upscaling is done by the crate image and the encoding algorithm is hardcoded and is the heaviest. I planned to have a configurable algorithm, but I haven't implemented it.

There is the option --use-scaled-window which makes wpaperd draw a surface of the size of the scaled screen. I.e. on a 4k screen with scale 2, the surface will be as big as a FHD screen. The compositor will instead do the scaling. Does enabling this option improve the performance?

PS: I was thinking of opening another bug. But I throw this out here. wpaperctl get-wallpaper should perhaps work without arguments and default as in the config should be a valid monitor name.

I'll have a look as well, I completely forgot about how the default setting works :sweat_smile:

The CLI interface is locked while it renders, but not in a breaking kind of way. So it's fine.

The daemon works in a single event loop, so if it is blocked in some long task (like upscaling), it won't answer to the IPC server (and in turn the CLI).

tbaumann commented 1 year ago

I think it's actually a bit faster in --use-scaled-window mode. I hardly ever see the background un-blurred. If I loose 1.5 scaling factor on my screen I don't think I will ever notice. Thanks for the hint.

danyspin97 commented 10 months ago

Hi @tbaumann! I have just added a sampling-filter argument to wpaperd so now you can choose the sampling filter algorithm at startup. The default sampling algorithm has been changed from lanczos3 (heaviest) to triangle (good tradeoff).

You can find more information about the various algorithms here:

https://docs.rs/image/latest/image/imageops/enum.FilterType.html

If triangle algorithm is still not fast enough, I'd suggest trying nearest.

Let me know if this improves the situation for you!

tbaumann commented 9 months ago
› wpaperd --sampling-filter
error: unexpected argument '--sampling-filter' found

This should be from a build based on current master (rev "0975ea1a7c39e37b892723a195bee5837ad18c06")

danyspin97 commented 9 months ago

My apologies, I removed that option shortly after adding it. I updated the code and let openGL upscale the image accordingly, which should lead to significant performance improvement in your case. Can you please try and let me know?

tbaumann commented 9 months ago

No worries. Will test.

PS: --sampling-filter is still referenced in Changelog

tbaumann commented 9 months ago

It's blazing fast now

danyspin97 commented 9 months ago

Glad to know! Hardware acceleration did the trick :D I am closing this bug then, let me know if this issue appear again.