• jmmv
  • ·
  • 3 weeks ago
  • ·
  • [ - ]
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.

If you are curious, I ended up writing some more on this here: https://jmmv.dev/2019/03/macos-threads-qos-and-bazel.html

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.
  • jmmv
  • ·
  • 3 weeks ago
  • ·
  • [ - ]
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.

I thought this was a life hack recommendations article but it’s about Quality of Service.

@dang or @op can we get QoS added to the title?

  • jolmg
  • ·
  • 3 weeks ago
  • ·
  • [ - ]
I thought the same, but the parenthesized domain should be an adequate hint, to be fair.
I was thinking that maybe Apple had useful guidelines for how developers can prioritize their work. :)
I thought that too. I even thought of an explanation, involving tasks that impact multiple projects.
Here's a link to best practices for multitasking from the same domain: https://developer.apple.com/design/human-interface-guideline...
I fell for this one too.
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.
I actually thought you meant that this was about applying QoS algos to real life, before I saw the link lol.
  • ·
  • 3 weeks ago
  • ·
  • [ - ]
Additional reading about how Swift Structured Concurrency (Task API) utilizes and propagates QoS is in the proposal doc.

https://github.com/swiftlang/swift-evolution/blob/main/propo...

  • ·
  • 3 weeks ago
  • ·
  • [ - ]
Why would a dev use this? I want my app to perform as high as possible, regardless of other apps (published by other companies) on the system.

This should be a user-controlled feature, with tasks identified and labeled by the OS.

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.

If your app drains all the battery, or makes the phone laggy, users might avoid your app.
This isn't DOS 3.2, apps don't get the whole computer ever. Applications play nice in the multi-tasking world or they get replaced by ones that do.
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:

https://www.w3.org/2023/Talks/TPAC/breakouts/web-worker-qos/

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
I use more than one app at a time. If your app performs great and starves out all the others, then it’s going in the trash.