How to Slash Swift Debugger Breakpoint Delays in Large iOS Apps
The Youku iOS team investigated why first‑breakpoint pauses could exceed three minutes after a massive Swift migration, analyzed LLDB internals and external module dependencies, tried and discarded several refactoring and compiler‑flag approaches, and finally achieved a dramatic speedup by tweaking LLDB settings and adding a small Swift helper for missing property prints.
Introduction
Swift, announced at WWDC 2014, is a compiled language for macOS, iOS, iPadOS, watchOS and tvOS. After Swift 5.0 stabilized the ABI in 2019, Youku’s iOS team began migrating its large, component‑based app to Swift.
Problem: Slow First Breakpoint
During 2021 the team noticed that the first debugger breakpoint in the video playback module (over 70 k lines of code and more than 200 external dependencies) could take 180 seconds or more, severely hurting development efficiency.
Initial Analysis
Breakpoint latency correlated with the number of external modules, suggesting LLDB’s module‑loading and Any‑type parsing were the main culprits. Reducing the playback module’s external dependencies from ~200 to ~90 lowered the first‑breakpoint time only from ~200 s to ~120 s, indicating limited benefit from business‑layer decoupling.
Invalid Solutions
Attempting to disable the Swift flag -serialize-debugging-options (by adding SWIFT_SERIALIZE_DEBUGGING_OPTIONS=NO) improved speed but broke variable printing. Disabling “Generate Debug Symbol” in hundreds of libraries had no measurable effect.
Effective Solution: LLDB Configuration
By adjusting LLDB settings—setting target.memory-module-load-level minimal and disabling the Swift Clang importer with settings set symbols.use-swift-clangimporter false —the first‑breakpoint time dropped from ~180 s to ~40 s across various development environments.
Remaining Issues and Work‑around
After the LLDB tweaks, some Objective‑C properties could no longer be printed (e.g., po video.sid). The team added a small Swift helper function aliprint and bound it to a custom LLDB command, restoring the ability to inspect those properties.
public func aliprint(_ target: Any?, selector: String?) {
if let target = target as AnyObject? {
if let selector = selector {
let returnValue = target.perform(NSSelectorFromString(selector))
print("\(String(describing: returnValue?.takeUnretainedValue()))")
} else {
print("\(String(describing: target))")
}
}
}Custom command registration:
command regex px 's/(.+) (.+)/expr -l Swift -O -- import AliOneUtils; aliprint(%1,selector:%2);/'Conclusion
The Youku iOS team’s experience shows that, for large componentized iOS projects, tuning LLDB settings is far more effective than extensive code‑base refactoring for eliminating slow first‑breakpoint delays, while a lightweight Swift helper can mitigate the side‑effects on property inspection.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
