A number of years ago, I was working on the port of Bazel to macOS. One of the issues we faced internally at Google was that some of our users reported that Bazel builds randomly killed their Internet connection and that they performed poorly.
There was a lot of FUD around the topic, with some engineers blanket-claiming that "well, macOS is bad at threads, so there's that". I didn't buy that explanation because I had seen macOS under serious load in other occasions and none of this nonsense happened in them.
And then, almost by chance, I stumbled upon this QoS system, did a few spot-checks, and found that the VPN daemon was misconfigured to run at a low class. Consequently, Bazel starved the VPN for those users and made everything misbehave. Adjusting that one parameter fixed everything.
How would one go about changing QoS for the system daemons and would it require disabling SIP? I don't see anything relevant in launchctl's man or launchd documentation, really interested to try it on the system VPN service.
In that specific case, it was our own installation of a VPN client and a custom definition of its launchd configuration. I don’t remember the exact details anymore.
I’d expect the system-provided services to be correctly configured by Apple in this regard.
It's good practice to not editorialize the title when making a submission. You could misread many titles to mean something else, it's sort of a hidden assumption that you should read the article before commenting on it.
It doesn’t seem to me like the GP commented before looking at the article. I think it’s justified to clarify a title that’s prone to be misleading. That’s different from editorializing, which is inserting one’s own opinion or agenda in the title.
This kind of thinking is exactly why Electron-based apps end up consuming 4% CPU while doing nothing, and why some games use 100% CPU just sitting in their menus.
Why would you expect users to manage threads, processors, and system resources themselves?
I agree with you, but I wonder what the incentive is for developers to use resources responsibly. Is it just that users will uninstall apps that drain their battery? Or are there penalties imposed by the OS on developers who refuse to play nicely?
At a minimum this is done diligently for Apple-written software.
For foreground apps like electron actually this wouldn’t do anything because you generally want it to be foreground. However, various extensions probably should use a different QoS level because responsiveness is better (eg code indexing, builds, etc).
The incentive is a better user experience and a lot of times software engineers end up using the software they’re building so the self interest incentive exists. And developers also exist who view it as a craft and push themselves to write better software.
You might appreciate that many of these processes compete internally within a single app’s access to compute/networking. This is how a developer can prioritize within their own app’s processes.
Regarding prioritization across multiple apps’ processes, you might be surprised by just how considerate iOS developers can be. They (we!) tend to obsess over user experience, and knowingly adjust QoS to fit the user’s best position vs the app’s best position, understanding that such a values-first approach to development raises overall product quality. (You can call that “alignment.”) After all, it is literally a single line of code.
For my primary project minimal.app, I use .userInteractive QoS extensively for collaboration and sync, and otherwise fall back to a more appropriate QoS. The point that I have internalized is that this most crucial process (sync/collaboration) is an order of magnitude or greater more important than any other process. Of course I will internally prioritize this key process, and such internal prioritization naturally bleeds into the greater ecosystem appropriately, benefitting the user. This QoS system is so well-designed that my self-interest (or rather, my obsession with making my app as useful as possible) aligns across other apps and their self-interests.
That's not how this works. Fundamentally, any machine has finite resources and it is the kernel's responsibility to sort and prioritize more work than there are available resources to complete it. If you make no differentiation in priority of your app's tasks by saying "everything is important," then the kernel will treat truly important work as weighted equally as unimportant work. You can see how this is counterproductive, both to your app, the user of your app, and other apps running on the system written other developers.
Critically important is a metric that the doc notes: Apps should spend 90% of their time when they are not responding to UI-initiated tasks at "Utility" or less...and then there's a mechanism devs can use to actually see where their apps sit.
Setting a standard is helpful, but providing well-engineered mechanisms and monitoring to accelerate compliance is critical to achieving the intended overall effects (let's say, battery life).
If you are developing a web app, you are probably using it without knowing it by using the browser's runtime environment, which itself interfaces with the OS's task scheduling system, probably setting it's own UI tasks to higher priority.
There is a recent w3c proposal to add explicit support for QoS hints to web workers:
User experience? Developers do profiling, optimization, and the like all the time to make their apps smoother, faster, and less intensive on the system.
If every app did this properly, the benefit is that when you really need absolute highest priority for a task, you might actually stand a chance of getting it if every other app isn't doing exactly the same thing. But tragedy of the commons and all that..
I recently read a lot of Microsoft "The Old New Thing" blog where a few times were mentioned "Le Chatelier’s Principle as interpreted by John Gall: Every system resists its proper functioning". It was the first thing I thought of when reading about assigning quality of service, and here is your comment :P
There was a lot of FUD around the topic, with some engineers blanket-claiming that "well, macOS is bad at threads, so there's that". I didn't buy that explanation because I had seen macOS under serious load in other occasions and none of this nonsense happened in them.
And then, almost by chance, I stumbled upon this QoS system, did a few spot-checks, and found that the VPN daemon was misconfigured to run at a low class. Consequently, Bazel starved the VPN for those users and made everything misbehave. Adjusting that one parameter fixed everything.
If you are curious, I ended up writing some more on this here: https://jmmv.dev/2019/03/macos-threads-qos-and-bazel.html