This is the 31st day of my participation in the August Text Challenge.More challenges in August

Write in front: iOS underlying principle exploration is my usual development and learning in the accumulation of a section of advanced road. Record my continuous exploration of the journey, I hope to be helpful to all readers.Copy the code

The directory is as follows:

  1. IOS underlying principles of alloc exploration
  2. The underlying principles of iOS are explored
  3. The underlying principles of iOS explore the nature of objects & isa’s underlying implementation
  4. Isa-basic Principles of iOS (Part 1)
  5. Isa-basic Principles of iOS (Middle)
  6. Isa-class Basic Principles of iOS Exploration (2)
  7. IOS fundamentals explore the nature of Runtime Runtime & methods
  8. Objc_msgSend: Exploring the underlying principles of iOS
  9. Slow lookups in iOS Runtime
  10. A dynamic approach to iOS fundamentals
  11. The underlying principles of iOS explore the message forwarding process
  12. Dyld (part 1)
  13. IOS Basic Principles of application loading principle dyld (ii)
  14. IOS basic principles explore the loading of classes
  15. The underlying principles of iOS explore the loading of categories
  16. IOS underlying principles to explore the associated object
  17. IOS underlying principle of the wizard KVC exploration
  18. Exploring the underlying principles of iOS: KVO Principles | More challenges in August
  19. Exploring the underlying principles of iOS: Rewritten KVO | More challenges in August
  20. The underlying principles of iOS: Multi-threading | More challenges in August
  21. GCD functions and queues in iOS
  22. GCD principles of iOS (Part 1)
  23. IOS Low-level – What do you know about deadlocks?
  24. IOS Low-level – Singleton destruction is possible?
  25. IOS Low-level – Dispatch Source
  26. IOS bottom – a fence letter blocks the number
  27. IOS low-level – Be there or be Square semaphore
  28. IOS underlying GCD – In and out into a scheduling group
  29. Basic principles of iOS – Basic use of locks
  30. IOS underlying – @synchronized Flow analysis
  31. IOS low-level – The principle of lock exploration
  32. IOS Low-level – allows you to implement a read/write lock
  33. Implementation of Objective-C Block
  34. Implementation of Objective-C Block
  35. IOS bottom – Block, comprehensive resolution!

Summary of the above column

  • Summary of iOS underlying principles of exploration

Sort out the details

  • Summary of iOS development details

preface

After you’ve developed an APP, it’s on the shelf. So how do users feel about your APP in practice? Prime Minister, the APP responds quickly, starts up quickly, and there is almost no waiting for the user. This is basically a perfect APP. Therefore, it is easier for us developers to control the response of the APP and whether users need to wait for the operation. However, for the startup of the APP, how to optimize it so that our APP can start faster is discussed step by step today.

Start the concept

There are two definitions of startup:

  • Generalized: Click icon to home page data loaded
  • Narrow sense: Click the icon to Launch Image completely disappear the first frame

What we’re going to focus on today is the mian function demarcation, which we used to call pre-main; After that, let’s call it after main. Why do we divide it this way? Because Xcode provides us with a good monitoring tool, it can monitor the elapsed time before the main function. In the iOS project, the first place to execute our code is the load method. Before the load method, system loading and link binding will have a lot of influence on our startup time, but it is difficult for us to monitor.

So, this tool gives us all the time that dyLD has spent. How do you use this monitoring tool? See the following figure (configuring an environment variable) :

After the configuration, connect to the real machine and run the project. Here, take one of my projects as an example, there will be the following log content:

  • Dylib loading time: dynamic library loading time;
  • Rebase /binding time: reposition, rebind;
  • ObjC setup time: OC class register (OC is a dynamic language, read binary data content, find information about OC, register OC class; The OC runtime needs to maintain a mapping table (sel and IMP mapping, global table of classes and class names, all classes need to be loaded into the global table when loading Mach-O).
  • Initializer time: The time required to execute the load and constructor functions.

rebase/binding time

  • Compile-time linking (Macho-o tells Dyld that I need to use an external library (maybe the Fundation API should be saved for runtime binding)
  • Runtime binding

Virtual memory

Physical address age

Early Mach-O was all physical memory, that is, the real memory address after the reference was loaded into memory.

  • This can be problematic:
  • 1. It’s easy to run out of memory;
  • 2. Security issues.

Lazy loading mode

When the system engineer optimizes, because the application does not need all the functions at the beginning of loading, so the application is loaded into memory on demand, and the user needs to load where? This will solve the memory shortage problem. But it will cause the application in the memory address of the discontinuous problem (will cause the running process of calculation, because the application of memory is not continuous so need to calculate, for program development is very inconvenient).

Once again, the system engineers solved the above problem with a mapping table (MMU memory management unit – translation address added to the hardware). Our application only finds the virtual memory table of the mapping table (addresses are continuous) and translates it into physical memory addresses through MMU to optimize the system.

To improve translation efficiency, memory is managed through pages (16K on iOS, 4K on Mac).

Physical memory addresses are managed by the operating system. Applications can only operate virtual memory addresses. In this way, the memory shortage problem is solved, and the security problem is solved. Because the application can only access its virtual memory table, the physical memory is well isolated. Moreover, processes are securely isolated from each other.

At this time, virtual memory is actually not safe, because every time we load the reference program virtual memory starts from 0, we calculate the offset address of a file, each time can be accessed through the memory address. Later, the operating system used ASLR to make the actual location of virtual memory generated each time start at a random value. (ASLR + offset = rebase)

When a user uses process 1’s P2 function while in use, the operating system reports a page missing exception (page missing interrupt) because P2 is not loaded into memory, which interrupts the user’s operation and then loads P2 into memory. Which memory to load into, this is the system through an algorithm (page displacement), to override the less active parts.

Binary rearrangement

Startup has local characteristics, that is, only a small number of functions are used at startup, and the distribution of these functions in binary is scattered, so the utilization of data read by page replacement is not high. If we can arrange the startup functions into the binary continuum, we can reduce the number of page swaps and optimize the startup time.

In the following diagram, methods 1 and 3 are used at startup, and two Page In are required to execute the corresponding code. If we put methods 1 and 3 together, we only need one Page In, thus increasing startup speed.

The linker LD has a parameter, -order_file, that supports ordering binaries in symbolic order.

In the next post, we’ll look at how to do binary retakes in detail.