A brief history of scheduled tasks

We all rely on our Macs to perform scheduled tasks, such as backing up, tidying up its working files such as the log, and a myriad of other things we’d rather not know about. Those were few in number in the days of Classic Mac OS, and generally left to individual apps, or entrusted to the user. When Mac OS X came it brought with it the cron service and its timetable crontab, but that was soon intended to be replaced by a new process manager launchd, then being developed by Dave Zarzycki, and released in Mac OS X 10.4 Tiger in 2005.
launchd
In this new model, one of the early tasks of the kernel after it has started booting is to load launchd, which then becomes the master launcher and launches everything else, in conjunction with launchctl and property lists in LaunchDaemons and LaunchAgents folders in Library folders. In replacing cron, launchd took on the responsibility of running scheduled background activities too.
The first couple of years with launchd had their moments, as it took a while before it became reliable. Just over two years later, when Apple released Time Machine in Mac OS X 10.5, its hourly backups were scheduled using launchd. The disadvantage of that was that, like cron, launchd isn’t flexible on timing: the moment it decides to run a large backup could coincide with intense user activity, resulting in noticeably slowed response and prolonged backup duration.
By far the best way of adding to or tweaking the property lists used by launchd is using a GUI editor such as Peter Borg’s Lingon X, shown below in one of its early incarnations in 2016.
A service that runs every day might be set up like this Adobe service. Each time that my Mac starts up, and every twenty-four hours afterwards, this will automatically run the background service named AGSService. You could configure a similar service to synchronise the contents of a working documents folder with that on a file server, for example, in the same way. Instead of using a repeat interval like this, you could set a fixed time each day, perhaps.
DAS-CTS
In 2014, with OS X 10.10 Yosemite, Apple introduced a whole new system designed to schedule background activities more flexibly, Duet Activity Scheduler (DAS). This is related to CoreDuet, a subsystem concerned with monitoring environmental and process load conditions. DAS maintains a list of scheduled activities, and frequently evaluates those activities to determine which should be run next. It does that by scoring them, taking into account the window in which the activity should occur, its priority expressed in terms of Quality of Service (QoS), current load on CPU cores, and environmental conditions.
Those are combined to produce a score: when that exceeds a threshold, DAS decides to run that activity, and will in turn tell Centralized Task Scheduling (CTS) to do so via lightweight inter-process communication (XPC). Once that’s complete, the next run will be scheduled with DAS, which puts that activity back into its scheduling list. This and other processes are summarised in the following diagram, based on what happens when scheduling routine hourly backups using Time Machine, in 2023.
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. Its configuration file com.apple.backupd-helper.plist schedules an XPC service com.apple.backupd-auto with the following key-value pairs for its background activity:
Interval: 3600 seconds = 1 hour, the average interval between repeats,
Delay: 3600 seconds = 1 hour, the time period before starting,
GracePeriod: 1800 seconds = 30 minutes, the time period to allow before scheduling becomes more aggressive,
Repeating: true
AllowBattery: true allowing backups when running on battery,
PowerNap: true
Priority: Utility setting the Quality of Service (QoS).
During startup, these property lists and their dictionaries are assembled into a list of activities for DAS. Those for most if not all macOS background activities are put in the group com.apple.dasd.default. Entries contain the contents of the dictionary for each activity for DAS to use when rescoring activities to determine which should proceed, and which should not.
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, typically every minute or less, DAS rescores activities in its list to determine whether each can be run, or shouldn’t be run at that time, given its policy scores. There’s no 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.
Scoring is weighted by policies that may include:
application, 25.0
battery level, 1.0
boot time (how long since the last boot), 0.01
CPU usage, 5.0
energy budget, 1.0
memory pressure, 5.0
network quality, 8.4
power nap, 5.0
charger connected, 10.0 or 20.0
thermal, 5.0
where the figure given for each is a typical value of its weighting in the overall scoring system.
DAS had a troubled start, rumoured to be the result of a slow memory leak. In macOS Sierra, Macs backing up using Time Machine that were left running for more than a week usually stopped making those backups after a few days. DAS even admitted to these in the new Unified log, in entries stating that “conditions are deteriorating”, followed by ominous silence. The only solution was to restart the Mac, and restore normal function to DAS. This was only fixed in High Sierra, and still afflicts Sierra.
These days, DAS is busier than ever, normally dispatching from a list of hundreds of activities. It’s just as well that it runs far more reliably.
Aperiodic
With launchd‘s daemons and agents, and DAS-CTS dispatching tasks, routine housekeeping in macOS ceased using periodic as it still does in some versions of Unix. For example, the introduction of the Unified log in Sierra brought a new log maintenance service logd to manage its log files. macOS Sequoia finally removed periodic, although cron remains available for the traditionalist, but is disabled by default. Maybe cron‘s days are also numbered and XPC will rule the tasks.