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:
- IOS underlying principles of alloc exploration
- The underlying principles of iOS are explored
- The underlying principles of iOS explore the nature of objects & isa’s underlying implementation
- Isa-basic Principles of iOS (Part 1)
- Isa-basic Principles of iOS (Middle)
- Isa-class Basic Principles of iOS Exploration (2)
- IOS fundamentals explore the nature of Runtime Runtime & methods
- Objc_msgSend: Exploring the underlying principles of iOS
- Slow lookups in iOS Runtime
- A dynamic approach to iOS fundamentals
- The underlying principles of iOS explore the message forwarding process
- Dyld (part 1)
- IOS Basic Principles of application loading principle dyld (ii)
- IOS basic principles explore the loading of classes
- The underlying principles of iOS explore the loading of categories
- IOS underlying principles to explore the associated object
- IOS underlying principle of the wizard KVC exploration
- Exploring the underlying principles of iOS: KVO Principles | More challenges in August
- Exploring the underlying principles of iOS: Rewritten KVO | More challenges in August
- The underlying principles of iOS: Multi-threading | More challenges in August
- GCD functions and queues in iOS
- GCD principles of iOS (Part 1)
- IOS Low-level – What do you know about deadlocks?
- IOS Low-level – Singleton destruction is possible?
- IOS Low-level – Dispatch Source
- IOS bottom – a fence letter blocks the number
- IOS low-level – Be there or be Square semaphore
- IOS underlying GCD – In and out into a scheduling group
- Basic principles of iOS – Basic use of locks
- IOS underlying – @synchronized Flow analysis
- IOS low-level – The principle of lock exploration
- IOS Low-level – allows you to implement a read/write lock
- Implementation of Objective-C Block
- Implementation of Objective-C Block
- 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.