Why some apps sometimes launch extremely slowly
So far, I have looked at slow launching in two apps, Pages and Calibre. Many of the complaints about the slowest to launch have been levelled at apps in Affinity’s popular suite. Thanks to the efforts of Alain, who generously obtained and provided me with log extracts, I can now try to explain why some apps may launch extremely slowly, occasionally taking more than 30 seconds, and on some Macs several minutes.
Previous work
In the first of my investigations, I demonstrated how Pages and Calibre could take a long time checking frameworks in their app bundle, and how that appeared to account for modest delays. I then looked more closely at Calibre, and found an association between slow launching and cache misses when checking frameworks. One possible explanation for that is the recomputation of SHA-256 hashes used to generate the CDHashes that both identify and verify protected code, and in my third article I showed how that could account for large differences seen in older models.
Affinity Designer 2
Alain has provided me with two particularly valuable log extracts from his MacBook Pro M1 Pro running macOS Monterey. Both were collected during launches of Affinity Designer 2, one from a very slow launch taking close to 30 seconds, and the other from a normal, brisk launch taking little more than a second.
Differences between those are stark: the slow launch took 23.5 seconds from mouse-click to loading user preferences for the app, of which 22.3 seconds was accounted for by framework checks, all of which were cache misses. The fast launch took a total of only 1.0 second and didn’t record any framework or other security checks at all, as it was performed about 12 minutes after the slow launch took place.
Framework checks
Framework checks performed during the slow launch consisted of a similar sequence of log entries to those seen in Pages and Calibre:10.943986 AppleSystemPolicy Waking up reference: 173
10.944007 AppleSystemPolicy Thread waiting on reference 173 woke up
10.944014 AppleSystemPolicy evaluation result: 173, allowed, cache, 1745876410
10.952412 AppleMobileFileIntegrity AMFI: constraint violation /Applications/Affinity Designer 2.app/Contents/Frameworks/liblibpersona.dylib has entitlements but is not a main binary
10.961105 amfid Entering OSX path for /Applications/Affinity Designer 2.app/Contents/Frameworks/liblibpersona.dylib
10.982192 Security SecTrustEvaluateIfNecessary
10.987489 Security SecTrustEvaluateIfNecessary
11.007538 Security SecTrustEvaluateIfNecessary
11.011106 Security SecTrustEvaluateIfNecessary
11.012004 com.apple.syspolicy.exec Recording cache miss for <private>
20.898736 AppleSystemPolicy Waking up reference: 174
Entries here differ slightly from excerpts for Pages and Calibre, as these are from Monterey rather than Sonoma.
In that case, the time interval between ‘waking up’ the two references is the checking cycle time for liblibpersona.dylib in the app’s Frameworks folder, an amazing 9.955 seconds. That dylib is 1.08 GB in size, and the largest of all the components in the app’s frameworks. If that period was accounted for by computing the dylib’s SHA-256 hash, that would represent a rate of 108 MB/s.
Checking cycle times varied greatly, ranging from 0.03-9.96 seconds over a total of 61 frameworks. As the total size of the Frameworks folder is 2.3 GB, the overall rate is 103 MB/s, similar to that for liblibpersona.dylib alone.
What’s being checked?
Log entries don’t provide any information as to what SecTrustEvaluateIfNecessary is likely to perform on these frameworks that can take anything from 0.03-9.96 seconds for each framework. Many of them are far too short to involve any online check, and in any case those are distinctive in their log entries. Malware scan using any known Yara rules is most unlikely, as:
- XProtect Yara rules commonly include file size limits, resulting in few rules applying to larger files, and more rapid completion.
- Known checks using Yara rules are all well-recorded in log entries, and the source of those rules is stated clearly.
- Yara scans are normally reported with their result.
- Scan results are succinct and hardly likely to be lost in a ‘cache miss’.
The most likely activity to account for these long checking times is computation of SHA-256 hashes for the contents of each item in the app’s Frameworks folder. Thus, these occasional extremely long launch times are most probably due to time taken ‘evaluating trust’ by computing hashes for protected code in the Frameworks folder in the app bundle, when those hashes have been flushed from their cache.
Why so extremely slow?
Several events have been credited with causing very long launch times, among them starting the Mac up, and installing updates to XProtect data. It appears most likely that the latter might act indirectly, by flushing at least some of the caches, which may be intentional.
Workarounds
The only strategy that does appear to stop long launch times in most cases is to disable SIP and, in the case of Apple silicon Macs, to set the security mode to Permissive. As I have noted on several occasions, that results in major changes in app security as well. It also disables some features that may be required, including Wallet and Apple Pay. It’s worth being aware that, once so disabled, if those features are to be restored they have to be created from scratch again, and can’t simply be toggled back on. Other side-effects of Permissive Security mode include the refusal of some App Store apps to run.
Those who find the occasional extremely slow app launch unacceptable, but wish to continue to run in Full Security, can pre-warm apps likely to be affected at the start of each session, so making it unlikely that subsequent launches during that session will be slowed. So far, reports of extremely slow launches in Sequoia appear less common, so there may also be benefits to updating macOS if that’s feasible.
Conclusions
- The most likely cause of extremely slow app launches is security checking of frameworks and similar within the app bundle, when cached checks aren’t available.
- Time taken for those checks is dependent on the size of the protected code being checked, and is most probably attributable to the computation of SHA-256 hashes.
- Pre-warming the app by launching it early in each session is a feasible strategy to avoid delays in launching it later.
- Although these extreme delays appear to be most common on Intel Macs, they can still affect older Apple silicon chips such as the M1 Pro.
I’m very grateful to Alain and Kristian who have generously run tests and provided their logs for my analysis, and their discussion.