Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Relevance of code minification in a performance...

Jitin
October 27, 2021

Relevance of code minification in a performance world

R8 and Proguard are Android developer's go-to tool for code minification. As a developer, inconsistent proguard rules can affect your application in more ways than you know. This talk will focus on code minification and it's additional impacts, divided into 3 parts
- Small introduction to code obfuscation and minification.
- Introduction to proguard rules, common mistakes and how to avoid them.
- A deep dive on how performance of app is impacted by proguard rules.

Jitin

October 27, 2021
Tweet

More Decks by Jitin

Other Decks in Programming

Transcript

  1. Relevance of code minification in a performance world Jitin Sharma

    GDE Android, Gojek Android Worldwide jitinsharma.com @_jitinsharma
  2. What we’ll discuss • Code obfuscation and minification • Introduction

    to obfuscation tools • Proguard rules • Performance impacts of code minification • Common mistakes and how to avoid them
  3. Obfuscation class Repository viewModel.fetchData() fun matchUser() val loggedIn = false

    package com.awesome.app class a c.zz() fun rt() val y = false package com.g.f
  4. Minification fun main() { fetchUser() } fun fetchUser() { fetchProfile()

    } fun fetchProfile() { displayProfile() } fun displayProfile() { .. } main() fetchUser() fetchProfile() displayProfile()
  5. Minification fun main() { fetchUser() } fun fetchUser() { //

    fetchProfile() } fun fetchProfile() { displayProfile() } fun displayProfile() { .. } main() fetchUser() fetchProfile() displayProfile()
  6. Minification fun main() { fetchUser() } fun fetchUser() { //

    fetchProfile() } fun fetchProfile() { displayProfile() } fun displayProfile() { .. } main() fetchUser() fetchProfile() displayProfile()
  7. Android Toolchain Code (source code + libraries) Obfuscation + minification

    D8/R8 minified dex AGP Toolchain (removes unused resources) manifest, resources apk dex/IR
  8. Android Toolchain Code (source code + libraries) dex/IR minified dex

    AGP Toolchain (removes unused resources) manifest, resources ResourceUsageAnalyzer.java apk Obfuscation + minification D8/R8
  9. Rules fun main() { val clazz = Class.forName() val method

    = clazz.getDeclaredMethod() method.invoke() } main() method()
  10. Rules fun main() { val clazz = Class.forName() val method

    = clazz.getMethod() method.invoke() } main() method() Classes Fields Interfaces Functions
  11. Comparison App Type Size App Launch Mode Non Minified 11.8MB

    596.6ms Release Minified 6.5MB 367.9ms Release Minified + Shrinked 6.4MB 361.3ms Release
  12. Code Inlining fun myBranchedFunction() { if (BuildConfig.DEBUG) { debugMethod() }

    else { releaseMethod() } } fun myBranchedFunction() { releaseMethod() }
  13. Code Inlining if (Build.VERSION.SDK_INT >= 21) { window.statusBarColor = ..

    } if (Build.VERSION.SDK_INT >= 28) { val displayCutOut = decorView.rootWindowInsets.displayCutout ... } minSdk 19 if (Build.VERSION.SDK_INT >= 21) { window.statusBarColor = .. } if (Build.VERSION.SDK_INT >= 28) { val displayCutOut = decorView.rootWindowInsets.displayCutout ... }
  14. Code Inlining if (Build.VERSION.SDK_INT >= 21) { window.statusBarColor = ..

    } if (Build.VERSION.SDK_INT >= 28) { val displayCutOut = decorView.rootWindowInsets.displayCutout ... } minSdk 21 window.statusBarColor = .. if (Build.VERSION.SDK_INT >= 28) { val displayCutOut = decorView.rootWindowInsets.displayCutout ... }
  15. Code Inlining if (Build.VERSION.SDK_INT >= 21) { window.statusBarColor = ..

    } if (Build.VERSION.SDK_INT >= 28) { val displayCutOut = decorView.rootWindowInsets.displayCutout ... } minSdk 28 window.statusBarColor = .. val displayCutOut = decorView.rootWindowInsets.displayCutout ...
  16. Code Inlining fun trim(String name) { Intrinsics.checkParameterIsNotNull(name) name(…) } fun

    trim(String name) { if (name != null) { name(…) } else { // exception } }
  17. Systrace Event Non minified Minified Mode bindApplication 54.46 ms 19.24

    ms Release ResourcesManager#getRes ources 4.62 ms 3.97 ms Release ResourcesImpl#updateCon figuration 3.98 ms 2.62 ms Release LoadApkAssets 1.3 ms 0.68 ms Release VectorDrawable#inflate 0.41 ms 0.39 ms Release
  18. Rules can hurt you - keep class com.mypackage.** - keep

    com.somepackage.R$* - keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }
  19. Transitive R classes App Module1 Module2 Module3 Module4 Module5 aar

    aar aar aar R.class R.class R.class R.class R.class R.class R.class R.class R.class
  20. 6.4 mb 361.3 ms Minified 6.6 mb (+3%) 487.1 ms

    (+34%) Minified with faulty rules
  21. 6.4 mb 361.3 ms Minified 6.6 mb (+3%) 487.1 ms

    (+34%) Minified with faulty rules Dex Count: 1 Dex Size: 634KB Dex load: 0.07ms Dex Count: 2 Dex Size: 894KB Dex load: 0.09ms
  22. Rules • Be aggressive instead of defensive when defining proguard

    rules. • Avoid wildcard package rules. • Use @Keep to attach rules to codebase instead of rules files. • Scan for rules which third party rules are importing in your codebase.