> SCHEDULING
> high-priority= Renice the daemon after startup to become a high-priority process. This a good idea if you experience drop-outs during playback. However, this is a certain security issue, since it works when called SUID root only, or RLIMIT_NICE is used. root is dropped immediately after gaining the nice level on startup, thus it is presumably safe. See pulseaudio(1) for more information.
> Takes a boolean argument, defaults to yes. The --high-priority command line option takes precedence.
> realtime-scheduling= Try to acquire SCHED_FIFO scheduling for the IO threads. The same security concerns as mentioned above apply. However, if PA enters an endless loop, realtime scheduling causes a system lockup. Thus, realtime scheduling should only be enabled on trusted machines for now. Please note that only the IO threads of PulseAudio are made real-time. The controlling thread is left a normally scheduled thread. Thus enabling the high-priority option is orthogonal. See pulseaudio(1) for more information.
> Takes a boolean argument, defaults to yes. The --realtime command line option takes precedence.
RLIMIT_NICE is of zero use with realtime audio.
This documentation is based on (1) the state of Linux circa 2008 or so (2) a complete misunderstanding of the role of nice values for scheduling (hint; it's only useful for altering the behavior of non-RT threads, which means threads that do not have hard or semi-hard timing deadlines).
It is a notable problem that there is so much out of date information about the use of nice with audio applications still circulating online. It was never true, and it's even less true today.
> a complete misunderstanding of the role of nice values for scheduling (hint; it's only useful for altering the behavior of non-RT threads, which means threads that do not have hard or semi-hard timing deadlines).
I suspect you're misreading the quoted documentation, I believe the quoted documentation is fine. To recite, "only the IO threads of PulseAudio are made real-time. The controlling thread is left a normally scheduled thread. Thus enabling the high-priority option is orthogonal (to SCHED_FIFO)".
Nice is applied to the controller responsible for other tasks, SCHED_FIFO is applied to the I/O threads, independently.
> On modern Linux systems, it is impossible for SCHED_FIFO to cause system lockups. [...] so even a SCHED_FIFO thread that runs "while (true){}" will not be allowed to use 100% of a core's cycles.
Really? The rtkit documentation mentioned,
> If processes that have real-time scheduling privileges enter a busy loop they can freeze the entire the system. To make sure such run-away processes cannot do this RLIMIT_RTTIME has been introduced. Being a per-process limit it is however easily cirumvented by combining a fork bomb with a busy loop.
> RealtimeKit hands out RT scheduling to specific threads that ask for it -- but only to those and due to SCHED_RESET_ON_FORK it can be sure that this won't 'leak'.
> In contrast to RLIMIT_RTPRIO, the RealtimeKit logic makes sure that only a certain number of threads can be made realtime, per user, per process and per time interval.
So "while (true){}" won't lock your system up, but "while (true) { fork(); }" certainly will, so the rational of only using SCHED_FIFO on trusted processes is reasonable.
I think it's still true. Is it?
Basically, read: https://access.redhat.com/documentation/en-us/red_hat_enterp...
(This is from RH, but the kernel params are generic)
Again, RTKit is a convenience wrapper, nothing more or less. It runs with sufficient priviledge to ask for SCHED_FIFO, which by default is not permitted. The more conventional approach is to create a user group and use PAM or equivalent to set the rt priority limit for that group, thus allowing any user in the group to run any app that can then ask for SCHED_FIFO with prio up to the limit. RTKit was created by Lennart to avoid this type of sysconfig (in favor of a different type of sysconfig).
You're mistaken about the historical ordering of things too. SCHED_FIFO was available long before PulseAudio or RTKit was created.
Yes, you could shuffle the text around as you suggest, but that's far from a "trivial" edit. It's basically equivalent to saying "yeah, the old doc was basically totally wrong, here's a correct version" :)
Pro-Tip: Hacker News has a "new comment cool-off timer", it gives a minute or two before allowing a comment to be answered. It gives a chance for the poster to edit the comment. Just relax when you cannot see a reply button.
> Basically, read: https://access.redhat.com/documentation/en-us/red_hat_enterp.... (This is from RH, but the kernel params are generic)
I see. "The default values for the Real-time throttling mechanism define that 95% of the CPU time can be used by real-time tasks. The remaining 5% will be devoted to non-realtime tasks (tasks running under SCHED_OTHER and similar scheduling policies). It is important to note that if a single real-time task occupies that 95% CPU time slot, the remaining real-time tasks on that CPU will not run. The remaining 5% of CPU time is used only by non-realtime tasks".
So a fork bomb is as safe is an empty loop (at least from a scheduling prospectively), as long as a strict limit is set.
I have noted it down.
> Yes, you could shuffle the text around as you suggest, but that's far from a "trivial" edit. It's basically equivalent to saying "yeah, the old doc was basically totally wrong, here's a correct version" :)
Okay, the main documentation for "man pulseaudio" was a bit better,
> To minimize the risk of drop-outs during playback it is recommended to run PulseAudio with real-time scheduling if the underlying platform supports it. This decouples the scheduling latency of the PulseAudio daemon from the system load a
You see, here it mentions real-time scheduling, not high-priority scheduling in "man pulse-daemon.conf". So I guess the explanation of " high-priority=" was more or less untouched since 2008, but the code kept moving on.
> You're mistaken about the historical ordering of things too. SCHED_FIFO was available long before PulseAudio or RTKit was created.
I meant the renicing mechanism was in PulseAudio before RLIMIT_RTPRIO, or the rtkit framework. I didn't say a word about SCHED_FIFO, which was indeed POSIX, but less useful without later improvement on scheduling policies.
Thanks for your patience and answers, all my questions have been explained.
The use of nice to try to adjust scheduling of audio apps (the entire application or specific threads) is completely off-base. If you use SCHED_OTHER, you're making a declaration that timing is not important. You can bump the nice value of a SCHED_OTHER thread, and that will change its behavior among the pool of the other SCHED_OTHER threads, but that's almost never useful in an audio app.
Now, ionice is another (and more complex) story ...
The point of rtkit is creating a convenient framework to enforce SCHED_RESET_ON_FORK and rate-throttling in a single place. So if I'm interpreting your comment correctly, running a "while (true) { fork(); }", even without restrictions of SCHED_RESET_ON_FORK, will not lock the system up in a modern system? Is it correct?
> The use of nice to try to adjust scheduling of audio apps (the entire application or specific threads) is completely off-base.
I think the renicing mechanism of "high-priority=" was historical, introduced to PulseAudio long before the system resource limit like RLIMIT_RTPRIO, or the rtkit framework has been put into place. As another document mentioned, g
> To minimize the risk of drop-outs during playback it is recommended to run PulseAudio with real-time schedulin [...] Alternatively, if the risk of locking up the machine is considered too big to enable real-time scheduling, high-priority scheduling can be enabled [...]
So while renicing is still here, PulseAudio prefers SCHED_FIFO nowadays, and the renice is only a fallback.
So, can you point out where exactly is wrong in the first documentation I quoted in the first comment? Certainly, the paragraph, "high-priority= Renice the daemon after startup to become a high-priority process. This a good idea if you experience drop-outs during playback" is outdated, but if one removes the word "Renice", and moves this paragraph from "high-priority=" to "realtime-scheduling=", it's still correct.
See here for more details: https://access.redhat.com/documentation/en-us/red_hat_enterp...
Plus highly contended critical sections should really really be avoided. So I'm not sure the author's benchmark even make any sense: if all of your workload is serialized, use a single thread.
That seems unlikely to me and doesn't match any experience I've ever had or known anyone to have. Can you explain what you mean by that?
Regular users of not so tuned apps probably experience this differently because Windows tries to do the tuning automatically and Linux doesn't.
The Windows scheduler has other issues, like random prio boosting to escape from prio inversion.
(Granted, the out of box behavior and the achievable latency are two separate issues)
I have never seen a mac box achieving reliable lower latency than Linux or Windows on the same hardware. Macs are nice for the plug'n'play experience - even though more often than not you still want to install your soundcard's driver.
But when it comes to doing actual work... https://www.dawbench.com/win7-v-osx-6.htm
If we're talking pure latency then UA, Focusrite, Apogee and Avid have lower RTL for the same buffer size in macOS. RME is identical on both platforms and I'm unsure about antelope.
Regarding loads before under-runs that's a very tough thing to test, as it varies between products. GENERALLY: Comparing Digital Performer between platforms heavily favours macOS. Comparing Pro Tools favours macOS (currently). Comparing Reaper favours windows slightly. Cubase favours Windows... etc...
There's also load type that factors in, as with macs you get a specific build with minimal leeway. Windows builds can be planned for a given build (highly serial, highly parallel, RAM hungry, Latency performant etc...). It's not too hard to build a test suite that favours macOS everywhere on the same machine, likewise for Windows.
But to the original topic, latency, macOS is generally superior in this regard when looking at RTL specs for the same device.
Speaking of which, do you know of a tool that would allow to ensure that e.g. your RT threads won't do bad things - short of putting a breakpoint on every syscall-like thing ? I wonder if at that point the audio community should not look into developing some clang-based static analyzer to enforce that.
Clang can be used for this but AFAIK you need to annotate functions/methods to indicate whether or not they are intended to be RT-safe. This gets complex if you have code that can be used in an RT context and in a non-RT context. The annotation part would be relatively simple in, say, a small audio player. In a DAW, it would be a substantial and complex task.
It's usually sufficient to do this in testing, and then have as is, in production.
There’s some potentially misleading information here. Background: I’ve spent the last 20+ years writing low-latency realtime audio applications, technically cross-platform but focused on Linux.
If you care about low latency on any general purpose OS, you need to use a realtime scheduling policy. The default scheduling on these OS’s is intended to maximise some combination of bandwidth and/or fairness. Low latency requires ditching both of those in favor of limiting the maximum scheduling delay of a thread that is otherwise ready to run.
Measuring how long synchronization primitives take without SCHED_FIFO is illustrative, but only of why, if you care about scheduling latency, you need SCHED_FIFO. There are several alternative schedulers for Linux – none of them remove the need for SCHED_FIFO if latency is important.
It is absolutely not the case that using SCHED_FIFO automatically starves non-SCHED_FIFO threads. Scheduling policy is set per-thread, and SCHED_FIFO will only cause issues if the threads that use it really do “burn the CPU” (e.g. by using spinlocks). If you combine SCHED_FIFO with spinlocks you need to be absolutely certain that the locks have low contention and/or are held for extremely short periods (preferably just a few instructions). If you use mutexes (which ultimately devolve to futexes at the kernel level), the kernel will take care of you a little better, unless your SCHED_FIFO thread doesn’t block – if it doesn’t do that, that’s entirely on you. Blocking means making some sort of system call that will cause the scheduler to put the thread to sleep – could be a wait on a futex, waiting for data, or an explicit sleep.
In particular, this: “This was known for a while simply because audio can stutter on Linux when all cores are busy (which doesn’t happen on Windows)” is NOT true. Linux actually has better audio performance than Windows or macOS, but only if the app developer understands a few basic principles. One of them is using SCHED_FIFO appropriately.
Pro-audio/music creation scheduling is MUCH more demanding than video, and a bit more demanding than games. Linux handles this stuff just fine – it just gives you enough rope to shoot yourself in the foot if you don’t fully understand what you’re doing.