Android Performance Tuning Guide

3 minute read

Kernel

configuration

  • remove unused kernel config
  • remove redundant device node
  • CONFIG_HZ
  • save memory with 32-bit kernel?

cgroup

  • cpuset CONFIG_CPUSETS
  • cpuctl cpu.share CONFIG_CFS_BANDWIDTH
  • memcg “/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes”

zram

  • Switch to LZ4 for better overall performance
  • Set max_comp_streams to num of cores since upstream also moves this to percpu.
  • Set page-cluster to 0 as the incremental cost of reading 1 page at a time is negligible for zram

fstab.%hardware%

+/dev/block/zram0                        none              swap    defaults                                            zramsize=536870912,max_comp_streams=4

init.%hardware%.rc

+    # ZRAM setup
+    write /sys/block/zram0/comp_algorithm lz4
+    write /proc/sys/vm/page-cluster 0

refer to commit 415b4cf.

mmc

  • check emmc spec version: freq, speed class
  • check emmc control supported spec version
  • blk-mq
  • read_ahead
     write /sys/block/mmcblk0/queue/iostats 1

iosched

  • BFQ (Budget Fair Queueing)
  • CFQ (Complete Fairness Queueing)
  • deadline
  • noop

The default io scheduler can be set by kernel parameter:

elevator=deadline

IOSCHED can also be changed later after system boot up:

cat /sys/block/mmcblk0/queue/scheduler
echo cfq > /sys/block/mmcblk0/queue/scheduler

cpufreq governors

  • Performance
  • Powersave
  • Userspace
  • Ondemand
  • Conservative
  • Interactive This governor was implemented by Google, it has following tunable parameters:
min_sample_time
hispeed_freq
go_hispeed_load
timer_rate
input_boost
boost
boostpulse

This is an example from shamu device’s rc file:

commit 5e8097fe919a17d8961d83936ebe66933b4a1bef
Author: elektroschmock <elektroschmock78@googlemail.com>
Date:   Tue Jul 17 13:34:14 2018 +0200

    shamu: Update interactive tunables

    Change-Id: Iafb8af84881d77ff580208bd8bf96d83001acd93

diff --git a/rootdir/etc/init.shamu.power.rc b/rootdir/etc/init.shamu.power.rc
index 8ce08665..733e065d 100644
--- a/rootdir/etc/init.shamu.power.rc
+++ b/rootdir/etc/init.shamu.power.rc
@@ -71,11 +71,11 @@ on property:dev.bootcomplete=1
     write /sys/devices/system/cpu/cpufreq/interactive/io_is_busy 1

     # cpufreq settings
-    write /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay "20000 1400000:40000 1700000:20000"
+    write /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay "20000 883200:40000 1190400:80000 2496000:100000"
     write /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load 99
-    write /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq 1497600
-    write /sys/devices/system/cpu/cpufreq/interactive/target_loads "85 1500000:90 1800000:70"
-    write /sys/devices/system/cpu/cpufreq/interactive/min_sample_time 40000
+    write /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq 1190400
+    write /sys/devices/system/cpu/cpufreq/interactive/target_loads "95 422400:58 652800:81 729600:74 883200:83 960000:8 1036800:6 1190400:85 2496000:87"
+    write /sys/devices/system/cpu/cpufreq/interactive/min_sample_time 60000
     write /sys/devices/system/cpu/cpufreq/interactive/timer_rate 20000
     write /sys/devices/system/cpu/cpufreq/interactive/max_freq_hysteresis 80000
     write /sys/devices/system/cpu/cpufreq/interactive/timer_slack 30000

For more details refer to kernel doc.

Scheduler

  • CFS
    1. parameters
      kernel.sched_child_runs_first = 0
      kernel.sched_latency_ns = 10000000
      kernel.sched_migration_cost_ns = 500000
      kernel.sched_min_granularity_ns = 2250000
      kernel.sched_schedstats = 0
      kernel.sched_time_avg_ms = 1000
      kernel.sched_tunable_scaling = 0
      kernel.sched_wakeup_granularity_ns = 2000000
      
    2. features
      GENTLE_FAIR_SLEEPERS
      START_DEBIT
      NO_NEXT_BUDDY
      LAST_BUDDY
      CACHE_HOT_BUDDY
      WAKEUP_PREEMPTION
      NO_HRTICK
      NO_DOUBLE_TICK
      LB_BIAS
      NONTASK_CAPACITY
      TTWU_QUEUE
      NO_SIS_AVG_CPU
      SIS_PROP
      NO_WARN_DOUBLE_CLOCK
      RT_PUSH_IPI
      RT_RUNTIME_SHARE
      NO_LB_MIN
      ATTACH_AGE_LOAD
      WA_IDLE
      WA_WEIGHT
      WA_BIAS
      UTIL_EST
      NO_ENERGY_AWARE
      EAS_PREFER_IDLE
      FIND_BEST_TARGET
      FBT_STRICT_ORDER
      NO_SCHEDTUNE_BOOST_HOLD_ALL
      
      echo NEXT_BUDDY > /sys/kernel/debug/sched_features
      
  • schedtune

Network

TODO

Android

graphics

  • Disable animation on low-end devices:
    settings put global window_animation_scale 0
    settings put global transition_animation_scale 0
    settings put global animator_duration_scale 0
    
  • OpenGLRenderer
    ro.zygote.disable_gl_preload
    ro.hwui.disable_scissor_opt
    ro.hwui.texture_cache_size
    ro.hwui.layer_cache_size
    ro.hwui.gradient_cache_size
    ro.hwui.patch_cache_size
    ro.hwui.path_cache_size
    ro.hwui.shape_cache_size
    ro.hwui.drop_shadow_cache_size
    ro.hwui.r_buffer_cache_size
    ro.hwui.texture_cache_flush_rate
    ro.hwui.text_small_cache_width
    ro.hwui.text_small_cache_height
    ro.hwui.text_large_cache_width
    ro.hwui.text_large_cache_height
    hwui.text_gamma_correction
    hwui.text_gamma
    hwui.text_gamma.black_threshold
    hwui.text_gamma.white_threshold
    hwui.use_gpu_pixel_buffers
    

    These properties can be set in device.mk with PRODUCT_PROPERTY_OVERRIDES, see OpenGLRenderer Configuration for more explanations.

From Android 9, the default renderer is skiagl, but, in some rare case, this will show glitches, so back to opengl:

setprop debug.hwui.renderer opengl
+# Fix graphical glitches on skiagl
+ PRODUCT_PROPERTY_OVERRIDES += \
+     debug.hwui.renderer=opengl
+

Visualize profiling of app rendering:

setprop debug.hwui.profile visual_bars
  • density

Dalvik

+ PRODUCT_PROPERTY_OVERRIDES += \
+    dalvik.vm.heapstartsize=16m \
+    dalvik.vm.heapgrowthlimit=256m \
+    dalvik.vm.heapsize=512m \
+    dalvik.vm.heaptargetutilization=0.75 \
+    dalvik.vm.heapminfree=2m \
+    dalvik.vm.heapmaxfree=8m

lmkd

lowmemorykiller kernel parameters:

cat /sys/module/lowmemorykiller/parameters/adj
0,100,200,300,900,906

cat /sys/module/lowmemorykiller/parameters/minfree
18432,23040,27648,32256,36864,46080

selinux

As said in commit f0b7005 file_contexts is slower than genfs_contexts, so move entries in file_contexts to genfs_contexts, if possible.

selinux regex file_context vs restorefs

other stuff

  • Avoid using logwrapper in init.rc

APP

  • Overrides onTrim
  • Avoid DecodeBitmap
  • Avoid overdraw
  • Reduce apk size
  • Convert images to WebP
  • gpu rendering
  • dumpsys gfxinfo package_name
  • framestats

launch time

  • Cold start system/extras/app-launcher/

Perf tools

References