Startup optimization It is in the cold startup phase of the APP. The initialization of various SDKS and the configuration initialization of our APP are counted as startup items. Generally we will heap they direct the AppDelegate – (BOOL) application: (UIApplication *) application didFinishLaunchingWithOptions: (NSDictionary *) the launchOptions method. At the beginning of the project, it was fine. Once there were more iterations of the project, the startup of various functions and SDKS increased sharply. At this time, we would find that the cold APP startup was slow, which greatly affected the user experience.

The knowledge point that boot item optimization governance needs to use has:

  • Mach-O
  • Compile the instruction__attribute__

Mach-O

Mach-o stands for Mach Object file format, which is a file format for executable files, Object code, dynamic libraries, and kernel dumps. As an alternative to the A.out format, Mach-O provides greater scalability and speeds up access to information in symbol tables. [Excerpt from Baidu Encyclopedia]

In short, Mach-o is an executable file on Mac/iOS. When we compile an iOS project, we usually produce an xxx.app file. When we right-click on the package contents, we can find a Mach-o file with the name xx.

Command otool -l XXX to view the contents of the Mach -o file:

Below is an excerpt of the contents of the Mach-o file

EasyLaunch:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedfacf 16777223          3  0x00           2    22       3344 0x00200085
Load command 0
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __PAGEZERO
   vmaddr 0x0000000000000000
   vmsize 0x0000000100000000
  fileoff 0
 filesize 0
  maxprot 0x00000000
 initprot 0x00000000
   nsects 0
    flags 0x0
Load command 1
      cmd LC_SEGMENT_64
  cmdsize 872
  segname __TEXT
   vmaddr 0x0000000100000000
   vmsize 0x0000000000004000
  fileoff 0
 filesize 16384
  maxprot 0x00000005
 initprot 0x00000005
   nsects 10
    flags 0x0
Section
  sectname __text
   segname __TEXT
      addr 0x0000000100001540
      size 0x0000000000000c43
    offset 5440
     align 2^4 (16)
    reloff 0
    nreloc 0
     flags 0x80000400
 reserved1 0
 reserved2 0
 ...
Copy the code

attribute

__attribute__ is a compilation instruction that specifies error checking during declaration and advanced optimization features.

Its position constraint is: placed at the end of the declaration “;” before

Attribute writing features: The attribute is preceded by two underscores, followed by a pair of parentheses, which contain the corresponding __attribute__ parameter.

The format of the attribute syntax is: attribute ((attribution-list))

Functions tagged attribute__((used)) are tagged in the target file to prevent the linker from removing unused sections.

Functions or variables that mark __attribute__((section(“new_section”))) are put into the new_section of the DATA segment by the compiler, not into the TEXT segment.

The principle of

By __attribute__, the function pointer that defines the startup item is placed under _easy_x in the DATA segment, and the content under the corresponding section is read at the appropriate time when the project is running, and the execution function can achieve the optimized governance of the startup item.

implementation

Start function entry definition:

#define EASY_REGISTER_LAUNCH_FUNCATION(key) __EASY_REGISTER_LAUNCH_FUNCATION(key)
#define __EASY_REGISTER_LAUNCH_FUNCATION(key) \
    static void __EASY_REGISTER_LAUNCH_##key(void); \
    __attribute__((used, section("__DATA," "_easy_" #key))) \
    static const void * __EASY__##key = __EASY_REGISTER_LAUNCH_##key; \
    static void __EASY_REGISTER_LAUNCH_##key(void) \
Copy the code

The startup function is used, implemented in a.m file:

EASY_REGISTER_LAUNCH_FUNCATION(LaunchSection_didFinishLaunching) {NSLog(@" execute LaunchSection_didFinishLaunching"); }Copy the code

After compilation, you can see how many sections there are in the Mach-o file:

Execute the specified boot option:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [EasyLaunch executeWithSection:LaunchSection_didFinishLaunching];
    return YES;
}
Copy the code

Read the implementation of the specified starter function pointer:

#ifndef __LP64__
#define mach_header_c mach_header
#else
#define mach_header_c mach_header_64
#endif

void _executeWithSection(long section) {
    Dl_info info;
    if (dladdr(&_executeWithSection, &info)) {
        struct mach_header_c *machHeader = (struct mach_header_c *)info.dli_fbase;
        NSString *s = [NSString stringWithFormat:@"_easy_%zd",section];
#ifndef __LP64__
        unsigned long size = 0;
        uintptr_t *data = (uintptr_t *)getsectiondata(machHeader, "__DATA", s.UTF8String, &size);
        if (data == NULL) {
            return;
        }
        int count = (int)(size / sizeof(void *));
        for (int i = 0; i < count; ++i) {
            void (*function)(void) = (void (*)(void))data[i];
            (function)();
        }
#else
        const struct section_64 * section64 = getsectbynamefromheader_64(machHeader, "__DATA", s.UTF8String);
        if (section64 == nil) {
            return;
        }
        uint16_t step = sizeof(void *);
        for (uint16_t offset = section64->offset; offset < section64->offset + section64->size; offset += step) {
            void (**function)(void) = (void (**)(void))((uint64_t)machHeader + offset);
            (*function)();
        }
#endif
    }
}
Copy the code

Attached source code: EasyLaunch

Reference:

Meituan Takeout iOS App cold start management