-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The Linux evdev sound API is very slow to open(2) the device #6
Comments
I would just use a single
As to why new beep would be slower than old beep, I will have to think about that a bit first. |
Thank you for the feedback. To clarify, slowdown is introduced by beep invocations, which is why the |
Sorry I misunderstood your actual concern. The original
here. That gives around 11ms per invocation, which is consistent with the
of the one invocation My system is an about 5 to 8 year old AMD A6-3500 3 core 2GHz(-ish?) with 16GB not at all swapping, running Fedora 29. |
Thank you. I will try the other permissions setups (“all other users” with Just to be safe, I downgraded beep to the original for a side-by-side comparison: #!/usr/bin/env -S bash --
beep -l 250 -f 262
beep -l 250 -f 294
beep -l 250 -f 330
beep -l 250 -f 349
beep -l 250 -f 392
beep -l 250 -f 440
beep -l 250 -f 494
beep -l 250 -f 523
I also compared strace output. It was identical in all the parts that could be reasonably expected to be identical. 😕 By the way, what were the “few serious security issues for |
The permission setup happens whenever the The permission setup does not happen when you run What is different between old beep and new beep? Old beep, for each beep it does, opens New beep opens I do not see those few milliseconds as a huge issue in practical use, but now that you have pointed this out I do want to know how exactly this happens, how this can be examined, and also how this could be improved (and what are the tradeoffs). Not my biggest priority, though. As to the security issues, see CVE-2018-0492 and CVE-2018-1000532. Both are covered in the johnath#11 issue. |
I was wondering about incidents reported, partly because I think it would be hilarious but mostly because I am curious about the CVE's relevance in the real world. Thank you for maintaining an interest in this bug. I am sorry I was not able to help much in pinpointing the cause. |
Being unfamiliar with either of them, I have just tried After inserting That is 100% code which I have written after taking over the beep source in order to separate the specific beeping API from the main The question is whether it makes sense for beep to support more than the |
The actual line which takes about 80% of startup time appears to be, as determined again via
Why? No idea. Opening that |
I just checked these two programs which just open the device file. Representing old beep with the console
and representing new beep with the evdev API:
It turns out that the console API skeleton takes between 1ms and 2ms and the evdev API skeleton takes 9ms to 14ms (BTW, directly So I would blame the additional 8ms to 12ms on the kernel, and, from a |
If I change these skeleton test programs to run the No idea why. |
You are very diligent. I tried the looped test and saw even worse results than you did (with
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void open_and_close(void)
{
//const int fd = open("/dev/input/by-path/platform-pcspkr-event-spkr", O_WRONLY);
const int fd = open("/dev/tty5", O_WRONLY);
close(fd);
}
int main(void)
{
for(unsigned int u = 0 ; u < 1000 ; u++)
{
open_and_close();
}
return EXIT_SUCCESS;
} How frustrating. |
As we found out in <#6>, opening the character device special files for the more modern evdev API takes about 5000 times the time needed for opening the device for the old console API: console API device name: /dev/ttyN (e.g. /dev/tty4) time per open-and-close cycle: about 3us evdev API device name: /dev/input/by-path/platform-pcspkr-event-spkr time per open-and-close cycle: about 15ms To help with measuring those times, and timing them with /usr/bin/time we have now added "issue-6-benchmark". Run "make issue-6-benchmark" to build "issue-6-benchmark". Read "issue-6-benchmark.c" or run "issue-6-benchmark --help" for usage information. One peculiar thing to note is that apparently, the evdev API takes neither User time nor System time, but still needs wall clock time: Command being timed: "./issue-6-benchmark 5118303 /dev/tty2" User time (seconds): 0.54 System time (seconds): 13.37 Percent of CPU this job got: 94% Elapsed (wall clock) time (h:mm:ss or m:ss): 0:14.75 Command being timed: "./issue-6-benchmark 958 /dev/input/by-path/platform-pcspkr-event-spkr" User time (seconds): 0.00 System time (seconds): 0.07 Percent of CPU this job got: 0% Elapsed (wall clock) time (h:mm:ss or m:ss): 0:14.66
Running
The first obvious thing is that 5407515 times opening the console device Now, let us read the output of For the console device, opening 5407515 times takes 0.58 seconds of user time, 14.89 seconds of system time, which about adds up to 16.51 seconds of wall clock time. Also, the console device causes 0 voluntary context switches and 10087 involuntary context switches. So far, so good. For the evdev device on the other hand, opening 1237 times takes 0.00 seconds of user time, 0.09 seconds of system time, which is just about nothing compared to the 16.63 seconds of wall clock time. So for more than 99% of the elapsed wall clock time, the computer appears to be doing things that are neither user time nor system time. Also, the evdev device causes 2475 voluntary context switches and 7 involuntary context switches. This is remarkably different from the case of the console device: Every Are just 2475 voluntary context switches taking all that 16.54 seconds of neither-system-nor-user time? Also, why is the time taken by context switches not be counted as system time? The time taken for the 7 involuntary context switches appears negligible, as the console device test case manages 10087 of those without causing taking too much time that is neither user time nor system time. At this time, I have not yet dug further down into the Linux kernel (glibc is probably not to fault, unless it exhibits different behaviour depending on the filename string passed to |
Record resource usage internally in addition to recording the elapsed wall clock time. This generates a report internally with all the resource and time usage which appears to be of importance first. At the end, it still runs externally via "/usr/bin/time -v" to make sure everything /usr/bin/time knows about is reported. Helps with #6 but does not fix it.
The following is example output of running
|
How can I add a rule to be able to write to /dev/vc/0 or /dev/tty0? I want to try this. Even using beep -l 1 -r 3000 seems to have delayed tones sometimes. Also why was the evdev API added? Is it because of the vulnerabilities? Nothing in those CVEs seem to indicate it was inherent to the console API. |
I do not know whether it is possible to add a rule for non-root users to write to I also do not consider it a big problem if there is some delay between starting So... about the APIs. The "console" API for the PC speaker (my term) works on the virtual console device ( So if you log in on a virtual console, you are running on a specific TTY device (e.g. Controlling the PC speaker beep via that console device made sense back then (probably in the 1990s), because you were obviously always running on a virtual console. I am not familiar with why the However, if you log in via graphical login and then start a virtual terminal program like Now while it is possible to have setuid-root executables or run executables via sudo for device access to the Anyway, someone came up with a better approach and created the new I do not actually know whether these were the actual reasons for the evdev API to be added. However, I can observe that the evdev API just makes sense, while the console API just has the air of a legacy API which was originally added without much thought about what Linux would be used for 10 or 20 years after its first implementation. So unless you use your computer like in the 1990s (text only and without being connected to today's networks), use the I guess the |
For the record, here is the Summarizing, the overall performance has increased from the old machine (A6-3500 APU 3 core) to the new machine by a bit over 30% for the console API, and by not quite 30% for the evdev API, so the ratio of console open+close to evdev open+close has not changed much (from 5800 times to 5900 times).
|
No I don't think the initial setup needs to be faster in any situation. I'm saying playing multiple tones with -n seems like there are tiny but perceptible delays using a low value for -l, less than 3 I think. Even for music there is no reason to use an -l value that low. The only case I can think of to do that would be sound effects in a retro style game. What do you mean by a non-user though, did you mean non-privileged user? Besides users writing to file, the only thing I can of that can be described as doing that is the kernel but that doesn't make sense to me. Here's the time using:
and the time with
|
Then we are not talking about console API vs evdev API. Have you read the (I am not saying
So... nothing
Sorry, typo. Yes, non-root or non-privileged users.
Nothing surprising here. The evdev API takes a few ms longer for opening the device, and 49 delays of 100ms between the 50 notes gives the same 4900ms. |
No I would not write a game in any POSIX shell. It seemed like evdev's time was diverging from the console's time which would affect C++ etc but I didn't think closely enough about it. |
Thank you for overseeing this project.
Cursed to use Arch Linux on one, last machine for the foreseeable future, one of the beep packages I use recently pointed its upstream URL your way (1.3-4 -> 1.4.4-1).
I set up permissions using the beep group method described in
PERMISSIONS.md
and immediately noticed sluggish, staggered response. Consider the following eight-note scale:In other words, your fork takes 23% longer to execute than it should--and it staggers from note to note. Do you know why? Do you know of any workarounds?
Thank you for reading.
The text was updated successfully, but these errors were encountered: