Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Mobile Fest 2018. Алексей Лизенко. Make your project great again

61 views

Published on

Можно ли улучшить пользовательский опыт и удобство разработки всего лишь оптимизацией Xcode проекта? Рассмотрим методики уменьшения времени запуска приложения и улучшения отзывчивости Xcode (довольно таки) малой кровью.

Published in: Education
  • Be the first to comment

  • Be the first to like this

Mobile Fest 2018. Алексей Лизенко. Make your project great again

  1. 1. MAKE YOUR PROJECT GREAT AGAIN Oleksii Lyzenko 2018
  2. 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. 3. WHAT YOU SHOULD EXPECT • Decrease application start time • Improve Xcode responsiveness • ??? • Get smarter !(also not bad)
  4. 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
  5. 5. APP LOADING • exec() • Load application into memory • Load dylibs • Rebase & bind • Obj-C runtime setup • Initializers • main() • applicationWillFinishLaunching() • Restore state • applicationDidFinishLaunching() • viewDidAppear()
  6. 6. PRE-MAIN TIME • You can not measure pre-main time from inside of your app :( • But in iOS 9 we got a new flag: DYLD_PRINT_STATISTICS
  7. 7. PRE-MAIN TIME • Console log:
  8. 8. PRE-MAIN TIME We can automate measurement with libimobiledevice: • ideviceinstaller to install app • idevicedebug to launch
  9. 9. COLD ❄ -VS- 🔥 HOT • Hot start • Cold Start
  10. 10. SWIFT Apple told us that Swift is Fun & Fast &Furious Looks like nothing to worry about • No so easy :(
  11. 11. SWIFT COMES TO PLAY • Empty project: Objective-C • Empty Project: Swift
  12. 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
  13. 13. App Dyld ZERO_PAGE APPLICATION LOADING • Leave 4GB ZERO_PAGE (64bit system) • System maps you application into memory • Address Space Layout Randomization (ASLR) • Loads & launches dynamic loader (dyld) • dyld resolves and loads all dylibs • dylibs might require other dylibs • dylibs require core signing check • Perform rebasing (adjust pointers inside image) • Perform binding (adjust pointers outside image) • Setup Obj-C runtime • Initialize Virtual Memory Space 0x0 0x???000 (random) A.dylib B.dylib ZZZ.dylib . . . Check WWDC 2016: Optimizing App Startup Time (session 406)
  14. 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. 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. 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. 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. 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. 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. 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
  21. 21. APP LOADING (AGAIN) • exec() • Load application into memory • Load dylibs • Rebase & bind • Obj-C runtime setup • Initializers • main()
  22. 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. 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. 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. 25. DEPENDENCY MANAGERS • Cocoapods • Carthage • Swift Package Manager • Submodules and your own hands 🤲 • All of them have (basic) static libraries support
  26. 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. 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
  28. 28. SWIFT COMPILATION MODES • Whole-module -wmo, -whole-module-optimization, -force-single-frontend-invocation A.Swift App B.swift Frontend Job C.swift A.Swift B.swift Frontend Job C.swift Frontend Job Frontend Job • Primary-file Linker App Linker Read and compile target file Read for metainformation Swift’s Github, Compiler Performance
  29. 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. 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. 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
  32. 32. Q&A Oleksii Lyzenko 2018

×