Xingfuli C-side iOS compilation optimization practice - 40% optimization time consumption

Xingfuli C-side iOS compilation optimization practice - 40% optimization time consumption

Author: Xu Binbin

background

After a long period of business iteration, the incremental compilation of C-side engineering has seriously deteriorated. Before December 2021, the average incremental compilation of C-side was more than 3 minutes, which seriously affected the R&D efficiency and urgently needed optimization! After optimization, the incremental compilation time was reduced to about 2 minutes.

analyze

Xingfuli app compilation process

Main time-consuming analysis

  • Full compilation: Pod compilation takes most of the time, up to hundreds of seconds, and CI packaging takes 20 to 30 minutes.
  • Incremental compilation: link and resource processing take up most of the time (this part takes 130s before C-side project optimization).

plan

LLVM compilation optimization

LLVM compilation process

The compilation of .m files from .o files goes through the following stages:

  • Preprocessing: remove comments, replace macro definitions, add line numbers and file identifiers
  • Lexical analysis: splitting the code into tokens
  • Syntax analysis: verify whether the syntax is correct and generate semantic nodes
  • Generate AST: combine all nodes to generate an abstract syntax tree
  • Static analysis: static code detection through syntax tree
  • Generate LLVM IR: CodeGen translates the syntax tree from top to bottom into IR code
  • Generate assembly: Convert IR code to assembly code
  • Generate object file: The assembler converts the assembly code into machine code

As you can see, a lot of work is done in the compilation process from source files to target files. If a new line of code is added to a source file, all R&D colleagues have to follow these steps again when building, which increases a lot of repetitive work and time.

dolphin distributed compilation cache

The Byte App Infra team hooks LLVM Clang. For basic compilation commands (such as oc files), they can be hashed into a unique key based on content and dependencies. After we compile the new .m, we store the corresponding .o and key on the local hard disk and remote server. When other R&D colleagues compile, they only need to download the .o file, which can greatly improve the compilation efficiency. After Xingfuli CI was connected to Dolphin, the time consumed for packaging and compilation was reduced from 600s to 240s.

Resource Optimization

Main project asset compilation

The main project resources will be compiled into Assets.car every time you compile. There are many images in the project stored under the resources of the main project. Each compilation will take more than 30 seconds at this step. Therefore, most of the main project image resources are migrated to the pod library, which can reduce the compilation time of the main project resources to within 5 seconds.

copy pods resource

Our project uses resources to reference resources. This step is to copy all pod library resources and compile and merge them into the main project's Assets.car, which takes about 40 seconds. There are two directions for optimization:

  1. If it is changed to resource_bundles, each pod will have its own bundle and its own Assets.car, and there is no need to compile it every time. The time consumption of incremental compilation will be reduced to 0, but the cost of project transformation is huge, so it can be regarded as a long-term goal.
  2. If we don't need to care about the UI interface, for example, when doing tracking, we can write a script to skip this step during compilation, which can be achieved in the short term.

Link Optimization

ld64

ld64 working principle reference: https://mp.weixin.qq.com/s/tSj6JVEg7plJQm7aDHLyMw

The static linker ld64 is responsible for analyzing the .o, .a, and .dylib files output by the compiler and other modules, and assembling executable files after parsing, redirecting, and aggregating symbols. The main workflow of ld64 is as follows:

zd

Zld is an optimized linker developed based on ld64. It increases the number of concurrency and uses more efficient data structures to optimize the link process. Of course, we can also participate in optimizing zld. For example, a big guy from Feishu optimized linear search through map search, reduced the time complexity of the algorithm, and optimized the time consumption of symbol resolution.

Linear Search

Map Search

Access zld data comparison

ld64 data:

zld data:

in conclusion

Data comparison:

Before optimization: 3.79m

After optimization: 1.91m

Practical tips

Resource copy

When the project is pod installed, a resource copy script code will be generated in pods-target-resources. This script will be run during compilation. If you want to skip resource copying, just add exit 0 to the first line of resources.

zld debugging

zld source code: https://github.com/michaeleisel/zld

Use zld to compile the project, view the compilation log, and obtain the link command code:

Delete the brackets and the contents inside, add a -v after the clang command to display the link parameters, then execute the script to generate link parameters, copy and delete the contents before -demangle, and save them to juzi.txt:

 -demangle -lto_library /Applications/Xcode.app/Content......

Open the zld project, adjust the compilation mode to release (debug runs too slowly, release runs fast but cannot be debugged with breakpoints), and copy the parameters of juzi.txt to arguments, then you can directly debug the link process of the project.

Analysis of zld time

Copy the release executable file generated by the zld project to the desktop.

Open the time profiler of instruments in Xcode and select the zld executable file on the desktop.

Replace \s- in the juzi.txt parameter with \\n-, copy it to the arguments in the figure above, and then run and analyze.

 -demangle \
-lto_library /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib \
-dynamic \
...

As shown in the figure, getUserVisibleName() takes a long time. Let's check the zld source code:

After breakpoint or log test, I found that this method can never find the substring of ".llvm." (only as a demo test), so I tried to change it to the following code:

Compile again to generate a new executable file, and test again with instruments to get the following data:

Todo

  1. Change resources to resource_bundles to reduce the resource copying time to zero.
  2. As Swift is used more and more in projects, you can use Dolphin to compile and cache Swift.
  3. Explore the industry trends of lld and further optimize link speed.

<<:  Do you know what threats your mobile devices face?

>>:  iOS 15.6 official version battery life test is out, it consumes more power

Recommend

BorgWarner eyes electric vehicle business, plans to make acquisitions again

According to foreign media reports recently, Borg...

How to set up the live streaming of massive Qianchuan delivery?

If you want to achieve good results when broadcas...

How Apple Watch can succeed as Android Wear struggles

[[128623]] Given the current slow development tre...

How to deploy new accounts in Juliang Qianchuan?

How can a new account conduct massive Qianchuan d...

Teach you step by step how to promote information flow videos!

Currently, the trend of online video advertising ...

Analysis of iReader vs. WeChat Reading Products

Books are the ladder of human progress, but paper...

How to do a good job in Zhihu promotion and traffic generation?

In fact, you only need to do these three things t...

A complete guide to self-media monetization in 2020!

Please read this article carefully! Then you will...

50 Tips for Marketing and Promotion at Station B

A while ago, an Airdesk video by the B station UP...

Advertising strategies for the Internet automotive industry (Part 2)

In the above article "Advertising Strategy i...

Google Play stops listing apps designed for older Android APIs

Google is very dissatisfied with the current situ...

"Lao Duan said: Make a box that doesn't get hot"

On November 1st, Skyworth iQiyi Ultra HD Box was ...