WWDC 22 Highlights
The ability to identify hangs in Xcode is a huge win for app performance
4 min read
This is my first blog post! After spending too long trying to design my own, I've decided to settle for Hashnode. Ultimately, my goal is to write series focusing on a single topic. To get started though, I'll be using it more like long-form Twitter by posting miscellaneous blurbs.
Of the many talks at WWDC 22, two in particular stood out to me.
The first was What's New in Xcode 14. The new build timeline should enable all developers to identify and improve compilation bottlenecks, and the ability to autoscale a single app icon to all sizes will allow my teams to drop some custom scripts and headaches. The real improvements, however, are about performance.
The new memory graph debugger shows upstream and downstream references and is much improved. Earlier this week, we had a strong reference cycle resulting in 100s of MBs of memory leaked. Xcode 13 was only able to find two conservative references to the leaked object. Xcode 14 also only showed two references, but if you click on the leaked object, you can see additional references that are not on the "shortest path to root". In our case, one of these hidden references was the root cause of the issue.
The second exciting performance improvement is that now – in addition to the Main Thread Checker – there is a Thread Performance Checker. In theory, this should be able to catch priority inversion during development which is a major source of regressions. Unfortunately, this does not seem to work in Xcode 14 Beta 1. Even very obvious priority inversions will not trigger a warning. This appears to be intentional though, as the new "Hangs" instrument is not visible in Instruments yet either.
Hangs with Xcode
That brings me to my second favorite talk: Track down hangs with Xcode and on-device detection. This talk did discuss the Thread Performance Checker, but that's not the only improvement when it comes to detecting Hangs. Another is that TestFlight users will be able to see when hangs occur and will be able to report them to developers by sharing on-device log files/tailspins.
By far though, the most exciting improvement is the addition of "Hang Reports" to the Xcode organizer. This will show aggregated hang data from your App Store users including the stack traces of the hangs. Better yet, this data is already available for all of your previous app versions. I downloaded Xcode 14 just to see this data and immediately began working on resolving our heaviest traces. All of our longest hangs were causes by priority inversion, which is why I'm hopeful the Thread Performance Checker works well once it's available. Unfortunately, I don't have any personal projects with enough users to receive this data, but here is where it would be if I did.
The addition of Hang Reports in Xcode was a bit bittersweet for me. I had just wrapped up a Swift port of Facebook's Delivering High Scroll Performance (associated blog post) which required exposing
execinfo.h to Swift, and using the
backtrace(3) call in a signal handler to gather traces of the main thread. In theory, this code could be used to gather much more granular hang data than what Apple provides, but the overhead of maintaining a complex Swift+C library, plus setting up a backend for symbolication makes it not worth it.
Now that the ticket has been closed as "Obsolete" I will seek permission to open source the code.
SwiftUI and concurrency updates were underwhelming compared to past years, but I am super excited about the new performance tooling. I've already downloaded Xcode 14 on my personal and work laptops, and I am trying to make a personal project using the Xcode 14 Multiplatform target. XcodeGen doesn't fully support this target yet, but this
project.yml gets most of the way there.
name: storytime-v1 options: bundleIdPrefix: com.jtbergman createIntermediateGroups: true generateEmptyDirectories: true groupSortPosition: bottom settings: # Prevents Xcode 14 from prompting to upgrade project settings DEAD_CODE_STRIPPING: YES targets: storytime-v1: type: application platform: iOS deploymentTarget: 14.0 info: path: Storytime/Metadata/Info.plist properties: # Without a launch screen, SwiftUI apps will be presented in a 3/4th size window UILaunchScreen: UIColorName: "" UIImageName: "" sources: - Storytime
The main thing missing is the ability to specify a dedicated Mac target under "Supported Destinations", but hopefully that will come soon.