ardaku / alloy

A fast and minimalistic image viewer forked from the now discontinued emulsion.
MIT License
16 stars 5 forks source link

strace alloy indicates constant invocations of getpid() and ioctl() in infinite loop #71

Open mh3663 opened 2 years ago

mh3663 commented 2 years ago

Having been curious as to why task switching from/to alloy and resizing of alloy windows seem so choppy, I instinctively did an »strace alloy 1.png« (1.png is one of the small images in alloy's resource directory making up its UI), which causes a constant flood of messages, seemingly without any intermittent delays.

All those rapid syscalls also explain the 1.5% CPU load with any open alloy window (emulsion too, both debug and release build). I did it on Linux (Kernel 5.18.1; on the same machine, gwenview, eog and feh use 0% CPU and radio silent on strace -- except when animating GIFs, which is fair).

Just 2 snippets of a typical alloy strace:

.
.
.
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
poll([{fd=3, events=0}], 1, 0)          = 0 (Timeout)
poll([{fd=16, events=POLLIN|POLLPRI}], 1, 1000) = 1 ([{fd=16, revents=POLLIN|POLLPRI}])
ioctl(16, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0x52, 0x10), 0x7ffe113bee30) = 0
sched_yield()                           = 0
ioctl(9, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0x2a, 0x20), 0x7ffe113bcf30) = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
epoll_pwait(4, [], 8, 0, NULL, 8)       = 0
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLIN|POLLOUT}], 1, -1) = 1 ([{fd=3, revents=POLLOUT}])
writev(3, [{iov_base="\22\0\f\0\2\0\300\2'\0\0\0\37\0\0\0\10\0\0\0\27\0\0\0001.png : "..., iov_len=96}, {iov_base=NULL, iov_len=0}, {iov_base="", iov_len=0}], 3) = 96
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
recvmsg(3, {msg_namelen=0}, 0)          = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLIN|POLLOUT}], 1, -1) = 1 ([{fd=3, revents=POLLOUT}])
writev(3, [{iov_base="\16\0\2\0\2\0\300\2", iov_len=8}, {iov_base=NULL, iov_len=0}, {iov_base="", iov_len=0}], 3) = 8
poll([{fd=3, events=POLLIN}], 1, -1)    = 1 ([{fd=3, revents=POLLIN}])
recvmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\1\30b\1\0\0\0\0\315\1\0\0\0\0\0\0\314\4\26\4\0\0\0\0\0\0\0\0\0\0\0\0", iov_len=4096}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 32
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
getpid()                                = 29005
.
.
.

...and other times, like this:

.
.
.
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
sched_yield()                           = 0
munmap(0x7fd5bf0b0000, 8192)            = 0
munmap(0x408b7000, 8192)                = 0
ioctl(9, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0x4f, 0x20), 0x7ffe113bf590) = 0
munmap(0x7fd5bef73000, 12288)           = 0
munmap(0x413db000, 716032)              = 0
ioctl(16, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0xcf, 0x10), 0x7ffe113bf5f0) = 0
close(16)                               = 0
ioctl(17, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0xcf, 0x10), 0x7ffe113bf5f0) = 0
close(17)                               = 0
ioctl(18, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0xcf, 0x10), 0x7ffe113bf5f0) = 0
close(18)                               = 0
ioctl(19, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0xcf, 0x10), 0x7ffe113bf5f0) = 0
close(19)                               = 0
ioctl(20, _IOC(_IOC_READ|_IOC_WRITE, 0x46, 0xcf, 0x10), 0x7ffe113bf5f0) = 0
close(20)       
.
.
.

Edited to add: I like pure image viewers like alloy as well as the fact that alloy is written in Rust. I have been unable to localize those incessant syscalls above, though. They don't seem to reside in any of the alloy or emulsion source files but rather in one of those uncounted Cargo dependencies.

I wouldn't be surprised if a multithreading-nonblocking messaging-I/O library like Tokio was the cause.

AldaronLau commented 2 years ago

Thanks for bringing this up!

I'm guessing this problem stems from either the winit crate (which pulls in mio) or glutin. I'm planning on doing some dependency reduction, and switch out winit for something that provides native headerbars (removing mio), as well as swap glutin for wgpu and that should fix the problem.

I think it's an inefficient immediate mode thing, where it has to draw every frame.