preface

Currently, most Android projects are built and compiled based on Gradle tools. At the beginning, when your project is not complex enough, or even small, you don’t need to worry about building optimizations. As the business becomes more complex, the amount of code increases, and there are more and more dependencies, The original single module project became a multi-module project, and the construction time became more and more.

For a large project, with so many modules and dependencies, which require more compile time, how can we reduce the build time? On the contrary, the bigger the project, the more time it actually saves.

In order to make build analysis more important to developers, Gradle has released build Scan, a tool that visually analyzes and diagnoses all build related data, and uses this analysis to help developers identify build problems and optimize build performance.

background

The App is a one-stop purchasing platform for small stores, which can quickly help small store owners complete stocking and other functions through mobile phones. With the continuous development of business, our project size and the amount of code also got great development, now our client project reached more than 40, the number of the module and involve the relevant dependent libraries has more than 200, has become a large project, can imagine a time when, I and my friends to you is very painful.

The problem

  • Generally, the normal compilation time of our project is about 3 minutes each time. If we compile several times consecutively, the time will be doubled accordingly. At the same time, the sound of computer CPU running will be louder and louder, and there will be an illusion that we are developing on the small Overlord learning machine. The most impressive compilation took more than ten minutes. Of course, the back becomes smarter, as long as you hear the small overlord learning machine sound, it means you can restart the computer.

    Author computer configuration: the company’s standard MacBook Pro, 16G memory, I7 processor

  • /gradlew clean assembleDebug command line compilation./gradlew clean assembleDebug command line compilation./gradlew clean assembleDebug command.

  • Module could not find classes in the indirect dependency library. After upgrading the Android Studio version, module in the project could not find classes in the indirect dependency library. However, it does not affect normal compilation and running. The reason is that *. Iml files do not automatically generate indirect dependencies from the library. Android Studio and Gradle may have a compatibility problem with earlier versions. This problem will be resolved after the latest version is upgraded.

The above compilation related problems consume precious time of me and my friends almost every day, and seriously affect the daily development efficiency. Therefore, when I saw the gloomy eyes of many friends who could not bear to compile for a long time, I thought it was time to start to solve these problems.

To solve

1. Upgrade Gradle

The first thing to do before you start any analysis and optimization work is to upgrade your Gradle version. This is the easiest way to make a difference. The new version usually means better performance and features

A guide on performance tuning would normally start with profiling and something about premature optimisation being the root of all evil. Profiling is definitely important and the guide discusses it later, but there are some things you can do that will impact all your builds for the better at the flick of a switch. Use latest Gradle and JVM versions, The Gradle team works continuously on improving the performance of different aspects of Gradle builds.

However, upgrading Gradle versions is not an easy task for our project. We have a dedicated internal packaging platform and introduced its packaging plug-ins, which rely heavily on earlier Gradle versions. Although internal packaging also provides plug-ins based on the new version, the attempt to upgrade resulted in compatibility issues and we were unable to follow the official Gradle version since internal packaging is usually only used during release or integration testing. Therefore, we have adopted another approach, which is to use the new version of Gradle for local daily development and compilation through script control. Internal platform packaging is still the same as the old version of Gradle packaging.

After upgrading Gradle and Android Gradle Plugin versions, the increase in compile time is significant. So, the lower the Gradle version you are using, the greater the improvement you will get when you upgrade to a new version.

2. Optimize and reduce modules

Let’s review Gradle’s build lifecycle:

  • Initialization phase: During the initialization phase, single or multiple project builds are supported, which determines which project modules to participate in the build and creates an engineering instance for each project module.
  • Configuration phase: In this phase, each project module is typically configured. And execute a portion of the script in the build of all project modules.
  • Task execution phase: After the initialization and configuration phases are completed, Gradle starts to execute each participating task.

Gradle provides a –profile command to help us know how much time is spent at each stage and to generate a report. , for example, you can perform the following command to get a report in the rootProject/build/report/profile / * * *. HTML

    ./gradlew assembleDebug --profile
Copy the code

The figure above is the report generated after the commands executed by our project, and the total build time took more than 3 minutes.

  • Summary: Build time Summary
  • Configuration: Time spent in the Configuration phase
  • Dependency Resolution: How long does Dependency Resolution take
  • Task Execution: The time at which each Task is executed

Task Execution time in the Summary Summary Summary is the sum of each module’s Execution time. In fact, tasks in multiple modules are executed in parallel.

Task Execution is the specific amount of time each module takes to compile. At the same time, you can also see that the cost of compiling a Module is relatively high, because there are many tasks to execute. So, the next step is to reduce and optimize these modules.

After rearranging our project modules, WE found that there were only two or three classes in some modules. There was no need for separate modules, which could be transferred to APP or Common-Business modules. Some of the core logic in modules has been isolated into aar references and optimized for residual code logic. After doing this, we reduced the number of engineering modules from over 40 to over 20, and yes, I killed nearly half of them.

Suggestion: If you can’t build a Module, don’t build a new one. If you really need to, you can use AAR instead. Aar compilation is cached, so it should be faster than Module in theory. If you’re interested, you can actually compare them

3. Some configuration optimization

  • – Added the Snapshot cache policy switch. In some cases, cacheChangingModulesFor 0, ‘seconds’ will be added to enable snapshot version changes to take effect in real time, but this will require a check to the cloud for changes every time you build. So, you can control this by adding a switch in local.properties to turn it off when it’s not needed.

    configurations.all { resolutionStrategy { if (rootProject.ext.cacheChangingModulesForDisable == false) { CacheChangingModulesFor 0, 'seconds' / / for dynamic configuration (such as 2 +) in the same way / / cacheDynamicVersionsFor 0,' seconds'}}}Copy the code
  • Avoid compiling unnecessary resources, such as unnecessary language localization

    android { ... productFlavors { dev { ... ResConfigs "zh", 'zh-rcn ', "xxhdpi"}... }}Copy the code
  • Gradle can save you a cup of coffee every day. Gradle can save you a cup of coffee every day

4. Other optimization

  • Script logic optimization, such as avoiding network requests or IO operations.
  • Eliminate duplication and unnecessary dependencies

The results of

Well, after all the above efforts, finally arrived at the moment of harvest. Because Gradle compilation time error is relatively large, in order to ensure the objectivity of the comparison results, we used the following command to compile three times before and after optimization:

    gradlew --profile --recompile-scripts --offline --rerun-tasks assembleDebug
Copy the code
  • --recompile-scripts: Bypasses caches to force script recompilation
  • --rerun-tasks: Forces all tasks to be rerun, ignoring any optimizations
  • offline: Offline mode compilation
Build number Before optimization The optimized decrement
For the first time, 3 minutes and 20 seconds 1 minutes and 59 seconds – 40%
The second time 2 minutes and 50 seconds 1 minutes and 7 seconds – 60%
The third time 2 minutes and 40 seconds 54 seconds – 67%

As can be seen from the above data, in the optimized project, the more compilation times, the less compilation time, and the actual speed increased by far more than 50%.

Also, after the upgrade, it is finally possible to compile with the Run button, and the fastest incremental compilation time is only 9s!

conclusion

Anacreontic students in the comments understand and summarize very in place, I directly posted up, thanks ~

  1. Upgrade to the latest gradle version and use the latest syntax like implementation instead of compile, etc
  2. Code level optimizations such as reducing aar dependencies for Modules
  3. Some other optimization configuration

feeling

Although our compile time has been reduced to more than 1 minute, there is still a lot of room for optimization. For example, in order to be compatible with older Gradle versions, we do not have a way to use implementation to replace compile, which can effectively reduce compile dependencies. We will also use Build Scan to further analyze and understand our build information.

If you’re working on a project where build build times are a burden, it’s important to pay attention. , perhaps, to the actual situation of each project may be different, but, I hope this article can provide some ideas for you, I believe, as you further analysis, there must be a better way to solve, in addition, it is important that there are few such a performance optimization, can bring real ascension effect in a short time, so, now, immediately start your build optimization.

If you have any questions or questions about build optimization, please leave a comment.

reference

Gradle Speed up: Saves you a cup of coffee a day

The last

A brief advertisement

Retailing is one of the five new strategies of Alibaba, as well as an army of entrepreneurs to explore a new retail model. With the rapid development of business, we are facing increasingly high technical challenges! To serve every store, only for every home is our mission. In order to better serve our mission, we need a large number of clients (Android & iOS), front-end and back-end students, looking forward to fighting with us!

Please send your resume to: [email protected]

On the occasion of double eleven, here is a photo of our team

PS: This advertisement is valid for a long time