Scheduled activities: 3 launchd or DAS?

In the first article in this series, I looked at how Duet Activity Scheduler (DAS) schedules background activities, then in the second article I showed how Centralized Task Scheduling (CTS) runs those activities when they’re called off by DAS. This article puts those together into a convenient chart, and contrasts them with how a simple LaunchAgent works.



In the example of periodic automatic Time Machine backups, the activity is specified in a LaunchDaemon property list, where it’s set to be repeating, at a given time interval and priority. During startup, in this case before the user logs in, the settings in that property list are used to register the activity with CTS, which then creates a new activity and submits that to DAS for scheduling. DAS uses the settings passed to determine that activity’s optimal score, and adds it to its list of activities.

Periodically, DAS rescores the activities in its list to determine whether each can be run, or shouldn’t be run at that time, given its policy scores. There doesn’t appear to be any way to examine that activity list, except by inspecting it in the log whenever DAS chooses to write details there. If an expected activity doesn’t occur, the only way to try to determine whether it has been scheduled by DAS is to browse the log.

When DAS decides that an activity can proceed, it tells CTS, which initiates the XPC activity and runs it to completion. Once complete, CTS initiates rescheduling by submitting the next task to DAS.

In the case of scheduled backup activities, the CTS activity isn’t the main task, but initiates the backup task, which then runs to completion in whatever time it takes. Accurate rescheduling is thus accomplished by the scheduled XPC activity completing quickly, ensuring that rescheduling doesn’t drift over time. It’s also up to the CTS activity to detect whether the previous main task has completed. This is particularly relevant to backups, which can take several hours. In those circumstances the main task doesn’t initiate another backup, but cancels that and leaves CTS to schedule the next.

DAS-CTS scheduling is now well-proven with macOS system activities whose timing is best kept flexible, and adapts with thermal load and other conditions.


Third parties, including users, are most unlikely to negotiate the complexities of DAS-CTS, and rely instead on conventional launchd scheduling of repeated tasks. In this, a simple LaunchAgent might be used with RunAtLoad set to true, and a StartInterval of 3600 seconds, to run a task every hour.

That won’t be scheduled or dispatched by DAS. Instead, typical log highlight entries from launchd might read:
6.245204 gui/501/co.eclecticlight.blowhole internal event: WILL_SPAWN, code = 0
6.245853 gui/501/co.eclecticlight.blowhole xpcproxy spawned with pid 51928
6.251844 gui/501/co.eclecticlight.blowhole service state: running
6.251862 gui/501/co.eclecticlight.blowhole Successfully spawned blowhole[51928] because interval
6.258190 co.eclecticlight.blowhole Blowhole snorted!
6.258590 gui/501/co.eclecticlight.blowhole exited due to exit(0)
6.258610 gui/501/co.eclecticlight.blowhole service state: not running
6.258661 launchd removing child: pid/51928

which ran my blowhole command tool, which doesn’t itself use XPC, to write the log entry Blowhole snorted!

That runs the task every hour exactly, regardless of other activities and conditions. In most circumstances, this is most appropriate. For instance, daily backups are normally run in the small hours of the morning. Heavier tasks which might clash with user activity are less suitable, though.

Priority and core allocation

Although priority is conventionally set in the property list for an activity, activities requiring significant computing resources should normally set their own Quality of Service (QoS) for their threads, which is then used to allocate those threads to the two different CPU core types in Apple silicon Macs. In any case, QoS set in property lists appears to be adjusted for use by DAS-CTS, for instance a Background QoS of 9 may be passed to scheduling as 5 instead. QoS moderation by macOS doesn’t appear to have been investigated or documented.