1 Dyld Steps
- Map all dependent dylibs, recurse
- Rebase all images
- Bind all images
- ObjC prepare images
- Run initializers
1.1 Loading Dylibs
- Parse list of dependent dylibs
- Find requested mach-o file
- Open and read start of file
- Validate mach-o
- Register code signature
- Call mmap() for each segment
1.1.1 Recursive Loading
- All your app’s direct dependents are loaded
- Plus any dylib’s needed by those dylibs
- Rinse and repeat
- Apps typically load 100 to 400 dylibs!
- Most are OS dylibs
- We’ve optimized loading of OS dylibs
1.2 Fix-ups
- Code signing means instructions cannot be altered
- Modern code-gen is dynamic PIC (Position Independent Code)
- Code can run loaded at any address and is never altered
- Instead, all fix ups are in __DATA
1.2.1 Rebasing and Binding
- Rebasing: Adjusting pointers to within an image
- Binding: Setting pointers to outside image
Rebasing
- Rebasing is adding a “slide” value to each internal pointer
- Slide = actual_address - preferred_address
- Location of rebase locations is encoded in LINKEDIT
- Pages-in and COW page
- Rebasing is done in address order, so kernel starts prefetching
Binding
- All references to something in another dylib are symbolic
- Dyld needs to find symbol name
- More computational than rebasing
- Rarely page faults
1.2.2 Notify ObjC Runtime
- Most ObjC set up done via rebasing and binding
- All ObjC class definitions are registered
- Non-fragile ivars offsets updated
- Categories are inserted into method lists
- Selectors are uniqued
1.3 Initializers
- C++ generates initializer for statically allocated objects
- ObjC +load methods
- Run “bottom up” so each initializer can call dylibs below it
- Lastly, Dyld calls main() in executable
1.4 Pre-main() Summary
Dyld is a helper program
- Loads all dependent dylibs
- Fixes up all pointers in DATA pages
- Runs all initializers
2 Improving Launch Times
2.1 Goals
- Launch faster than animation
- Duration varies on devices
- 400ms is a good target
- Don’t ever take longer than 20 seconds
- App will be killed
- Test on the slowest supported device
2.2 Launch recap
- Parse images
- Map images
- Rebase images
- Bind images
- Run image initializers
- Call main()
- Call UIApplicationMain()
- Call applicationWillFinishLaunching
2.3 Warm vs. cold launch
- Warm launch
- App and data already in memory
- App is not in kernel buffer cache
- Warm and cold launch times will be different
- Cold launch times are important
- Measure cold launch by rebooting
2.4 Measurements
- Measuring before main() is difficult
- Dyld has built in measurements
- DYLD_PRINT_STATISTICS environment variable
- Available on shipping OSes
- Significantly enhanced in new OSes
- Available in seed 2
- DYLD_PRINT_STATISTICS environment variable
- Debugger pauses every dylib load
- Dyld subtracts out debugger time
- Console times less than wall clock
2.5 Optimizing
2.5.1 Dylib Loading
- Embedded dylibs are expensive
- Use fewer dylibs
- Merge existing dylibs
- Use static archives
- Lazy load, but…
- dlopen() can cause issues
- Actually more work overall
2.5.2 Rebase/Binding
- Reduce __DATA pointers
- Reduce Objective C metadata
- Classes, selectors, and categories
- Reduce C++ virtual
- Use Swift structs
- Examine machine generated code
- Use offsets instead of pointers
- Mark read only
2.5.3 ObjC Setup
- Class registration
- Non-fragile ivars offsets updated
- Category registration
- Selector uniquing
2.5.4 Initializers
Explicit
- ObjC +load methods
- Replace with +initiailize
- C/C++
__attribute__
((constructor)) - Replace with call site initializers
- dispatch_once() dsfgsdfgsed
- pthread_once() 3452342
- std::once()
Implicit
- C++ statics with non-trivial constructors
- Replace with call site initializers
- Only set simple values (PODs)
-Wglobal-constructors
Rewrite in Swift
- Do not call dlopen() in initializers
- Do not create threads in initializers
3 TL;DR
- Measure launch times with DYLD_PRINT_STATISTICS
- Reduce launch times by
- Embedding fewer dylibs
- Consolidating Objective-C classes
- Eliminating static initializers
- Use more Swift
- dlopen() is discouraged
- Subtle performance and deadlock issues
Appendix
Related Documentation
Revision History
时间 | 描述 |
---|---|
2017-01-10 | 博文完成 |
Copyright
CSDN:http://blog.csdn.net/y550918116j
GitHub:https://github.com/937447974