Можно ли улучшить пользовательский опыт и удобство разработки всего лишь оптимизацией Xcode проекта? Рассмотрим методики уменьшения времени запуска приложения и улучшения отзывчивости Xcode (довольно таки) малой кровью.
2. WHAT WE ARE GONNA COVER
• Look at app loading process
• Application start time measurements
• Discuss basic virtual memory principles
• Speak about static and dynamic libraries
• Look at Xcode compilation flags
3. WHAT YOU SHOULD EXPECT
• Decrease application start time
• Improve Xcode responsiveness
• ???
• Get smarter !(also not bad)
4. WATCH DOG
• System will terminate your app if you
will exit watch dog timeouts
• User will quit your app before timeout
• Recommended launch time: 400ms
Scenario Timeout
Launch 20 sec
Resume 10 sec
Suspend 10 sec
Quit 6 sec
Background task 10 min
10. SWIFT
Apple told us that Swift is Fun & Fast &Furious
Looks like nothing to worry about
• No so easy :(
11. SWIFT COMES TO PLAY
• Empty project: Objective-C
• Empty Project: Swift
12. SWIFT COMES TO PLAY
• Swift has no binary compatibility
• Each Swift version has it’s own runtime
• Each app contains own dynamic swift libraries
• This are Swift runtime & system lib wrappers
• Should be fixed in Swift 4? 5? 6? 7?
• Specific Swift libraries in empty project
14. APPLICATION LOADING
• Usually app “contains” up to 400+ dylibs
• Empty app will “contains” 150+ dylibs
• How just 12 Swift libraries dropped performance so dramatically?
15. VIRTUAL MEMORY
Virtual Memory is a level of indirection
• Physical RAM pages addressed to virtual app pages
• Same RAM page can appear in multiple processes
• Page fault
• File backed pages
• mmap()
• lazy reading
• Copy-On-Write (COW)
• Dirty vs. clean pages
• Permissions: rwx
16. AppA AppBA.dylib
B.dylib YYY.dylib
ZZZ.dylib
AppA
A.dylib
B.dylib YYY.dylib
ZZZ.dylib
VIRTUAL MEMORY AND SHARED LIBRARIES
Virtual Memory
(App A)
Virtual Memory
(App B)
AppB
Real Memory
File system
AppB
YYY.dylib
AppA
A.dylib
B.dylib
ZZZ.dylib
A.dylib
B.dylib
Same
17. LIBRARIES FLAVOROUS
We should distinguish next libraries:
• System dynamic libraries (very optimized, stored in shared library caches)
• Third-party dynamic libraries
• Static libraries
18. STATIC LIBRARY
• Resolved in compile time
• Loads fast with main binary
• Can not contain resources (it’s just code)
AppA
A
B
ZZZ
19. DYNAMIC LIBRARIES (FRAMEWORKS)
• Resolved in runtime
• Can be shared between processes
• System frameworks
• App extensions
• Can be lazy loaded in runtime
• Can support versioning (frameworks)
• Can contain resources (frameworks)
AppA
A.dylib
B.dylib
ZZZ.framework
ZZZ.dylib
resources
20. LIBRARIES FLAVOROUS: CONCLUSION
• System dynamic libraries — fast, super easy to use
• Third-party dynamic libraries — slow, easy to use
• Static libraries — fastest, but you should pay attention
22. APP LOADING IMPROVEMENTS
• Reduce dynamic libraries count
• Reduce Obj-C usage (if Obj-C runtime phase is a problem)
• Avoid initializations on start:
• use + initialize instead of +load
• refactor static C++ objects
• FYI: Swift’s `static let` is lazy (Cool!)
23. REDUCE DYNAMIC LIBRARIES COUNT
• Cleanup codebase and remove duplicated libraries
• Avoid “one file” libraries (plenty of them in cocoapods)
• Use lazy loading with dlopen()
• Put library as sources
• Switch to static libraries…
24. STATIC LIBRARIES
• Static libraries are not allowed in Swift!!!
• Static libraries are allowed in Swift starting from Xcode 9.0
(stable work from Xcode 9.4)
25. DEPENDENCY MANAGERS
• Cocoapods
• Carthage
• Swift Package Manager
• Submodules and your own hands 🤲
• All of them have (basic) static libraries support
26. STATIC LIBRARIES: CONCLUSION
• We able to reduce app start time in several times
• Requires dependency manager support (and framework podspec update)
• Minor code changes (relative to other approaches)
• If framework contains resources you should move them to bundle by yourself
27. XCODE
• In Objective-C/C++/C-style:
• Hide all private content in .m/.cpp/.c file
• Expose in .h only what is absolutely necessary
• Write #import only when you need it
• Write @class (forward declaration) in headers if possible
• etc.
• Swift-style:
• Don’t care, I will do it all by myself!!!11one
29. XCODE MODULES
• Apple recommends to use Modules
• Now it’s possible to use Modules as static or dynamic libraries
• Good Modules breakdown can:
• Improve code decoupling
• Give some hints to compiler
• Give great performance boost for primary-file mode
30. ACTION POINTS
• Check you app start time
• Automate this process (CI) and collect statistic
• Determine bottlenecks and fix them
• Check your project’s dependencies, remove what possible
• You can move some libraries to static one
• Breakdown your project to modules
31. FURTHER READING
• WWDC 2016: Optimizing App Startup Time (session 406)
• WWDC 2012: iOS App Performance: Responsiveness (session 235)
• Jonathan Levin, Mac OSX® And iOS Internals, John Wiley & Sons, Inc, 2013 (this one is
sooooo goooood! And it’s available for free)
• Apple’s Dynamic Library Programming Topics
• Apple’s Memory Usage Performance Guidelines (About the Virtual Memory System)
• Xcode 9 Release Notes
• Swift’s Github, Compiler Performance
• https://github.com/libimobiledevice/libimobiledevice