Normal view

There are new articles available, click to refresh the page.
Today — 10 September 2025Main stream

Command tools, threads and QoS

By: hoakley
10 September 2025 at 14:30

Why is it that a fast Apple silicon Mac takes so long to tar and Gzip a large folder? Surely, with all those fast Performance cores, even GB should be compressed in the twinkling of an eye? Could it be that macOS is running the tar command on its Efficiency cores instead, eking out the power? This article explores and explains how macOS sets the priority for command tools and similar binaries.

Threads

There are two key factors at work here. The first is threading, division of the work done by a process into single flows of execution run on one CPU core at a time. Every process has its main thread, and many can also create additional threads that can be scheduled to run in parallel. While macOS can and often will move threads around its cores, a single-threaded process can only run on a single CPU core at a time.

QoS

macOS also allocates threads to cores. Although neither you nor the process control that absolutely, processes can influence it by setting a Quality of Service, QoS, for each of their threads. QoS is chosen from the standard list:

  • QoS 9 (binary 001001), named background and intended for threads performing maintenance, which don’t need to be run with any higher priority.
  • QoS 17 (binary 010001), utility, for tasks the user doesn’t track actively.
  • QoS 25 (binary 011001), userInitiated, for tasks that the user needs to complete to be able to use the app.
  • QoS 33 (binary 100001), userInteractive, for user-interactive tasks, such as handling events and the app’s interface.

There’s also a ‘default’ value between 17 and 25, an unspecified value, and you might come across others used by macOS.

If all your Mac’s CPU cores are free and idling, macOS will normally allocate threads with a QoS of 17 (utility) and higher to P cores, and those of 9 (background) and lower to E cores. That isn’t guaranteed, and there are circumstances when all threads are allocated to E cores alone, for example when a laptop’s battery is very low and it goes into energy-saving mode.

CPU History

It’s therefore tempting to assume that when a process runs very slowly, it’s being given a low QoS and is pottering along on the E cores. Although that might be correct, it’s a dangerous assumption to make. In this case, to investigate it further, I’ll take a different compressor that offers control over the QoS used for its working threads, such as my free Cormorant or the wonderful Keka.

When compressing an IPSW file of just over 18 GB, using Apple Archive’s LZFSE method in Cormorant takes 7.4 seconds at the maximum QoS of 33, but 114.7 seconds at the minimum QoS of 9. Performing exactly the same compression using aa from the command line takes about 9 seconds, so is clearly being run at high QoS. But using tar to create a tar.gzip takes forever, even longer than Cormorant running at minimum QoS.

Activity Monitor’s CPU History window is a quick and simple way to see what’s going on here, although you must be cautious when trying to interpret values such as CPU %., because those shown don’t take into account the frequency cores are run at.

This is Cormorant compressing at high QoS on all 10 of the P cores.

And this is the same compression performed at low QoS, so confined to the 4 E cores.

Compressing using aa in Terminal also makes full use of all the P cores available.

Running tar in Terminal does use the P cores, but runs in a single thread that’s shuffled between cores and takes more than 10 times as long as it would if it could be run in 10 threads.

Thus, the reason that tar is so slow isn’t because it’s given a low QoS and run on the E cores, but that it’s single-threaded (and not performant either). If you want better performance, look for a substitute that can make good use of multiple threads running in multiple P cores.

Exceptions

There are plenty of binaries that are run at low QoS, hence on the E cores, including most of those that are run in the background or scheduled using LaunchAgents and LaunchDaemons. Their property lists should specify a QoS name for their Priority key, which is often Background or Maintenance, for them to be run at a QoS of 9 or lower on the E cores alone.

There’s also the possibility that a command tool may run its own threads and assign a low QoS to them, although that should always be documented.

Summary

  • By default, command tools run in Terminal aren’t assigned low QoS and run on E cores.
  • Tools that run in single threads will invariably be slower than multi-threaded equivalents.
  • Use Activity Monitor’s CPU History window to see which core types threads are run on.

❌
❌