Clay Murphy | ca44e97 | 2015-08-24 17:57:30 -0700 | [diff] [blame] | 1 | page.title=Low RAM Configuration |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 2 | @jd:body |
| 3 | |
| 4 | <!-- |
Clay Murphy | 768b82a | 2013-11-12 11:32:41 -0800 | [diff] [blame] | 5 | Copyright 2013 The Android Open Source Project |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 6 | |
| 7 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 8 | you may not use this file except in compliance with the License. |
| 9 | You may obtain a copy of the License at |
| 10 | |
| 11 | http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | |
| 13 | Unless required by applicable law or agreed to in writing, software |
| 14 | distributed under the License is distributed on an "AS IS" BASIS, |
| 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 16 | See the License for the specific language governing permissions and |
| 17 | limitations under the License. |
| 18 | --> |
| 19 | <div id="qv-wrapper"> |
| 20 | <div id="qv"> |
| 21 | <h2>In this document</h2> |
| 22 | <ol id="auto-toc"> |
| 23 | </ol> |
| 24 | </div> |
| 25 | </div> |
| 26 | |
| 27 | <h2 id="intro">Introduction</h2> |
| 28 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 29 | <p>Android now supports devices with 512MB of RAM. This documentation is intended |
| 30 | to help OEMs optimize and configure Android 4.4 for low-memory devices. Several |
| 31 | of these optimizations are generic enough that they can be applied to previous |
Clay Murphy | 1606da4 | 2013-11-05 16:43:25 -0800 | [diff] [blame] | 32 | releases as well.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 33 | |
| 34 | <h2 id="optimizations">Android 4.4 platform optimizations</h2> |
| 35 | |
| 36 | <h3 id="opt-mgmt">Improved memory management</h3> |
| 37 | <ul> |
| 38 | <li>Validated memory-saving kernel configurations: Kernel Same-page Merging |
| 39 | (KSM), and Swap to ZRAM.</li> |
| 40 | <li>Kill cached processes if about to be uncached and too large.</li> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 41 | <li>Don't allow large services to put themselves back into A Services (so they |
| 42 | can't cause the launcher to be killed).</li> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 43 | <li>Kill processes (even ordinarily unkillable ones such as the current IME) |
| 44 | that get too large in idle maintenance.</li> |
| 45 | <li>Serialize the launch of background services.</li> |
| 46 | <li>Tuned memory use of low-RAM devices: tighter out-of-memory (OOM) adjustment |
| 47 | levels, smaller graphics caches, etc.</li> |
| 48 | </ul> |
| 49 | |
| 50 | <h3 id="opt-mem">Reduced system memory</h3> |
| 51 | <ul> |
| 52 | <li>Trimmed system_server and SystemUI processes (saved several MBs).</li> |
| 53 | <li>Preload dex caches in Dalvik (saved several MBs).</li> |
| 54 | <li>Validated JIT-off option (saves up to 1.5MB per process).</li> |
| 55 | <li>Reduced per-process font cache overhead.</li> |
| 56 | <li>Introduced ArrayMap/ArraySet and used extensively in framework as a |
| 57 | lighter-footprint replacement for HashMap/HashSet.</li> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 58 | </ul> |
| 59 | |
| 60 | <h3 id="opt-proc">Procstats</h3> |
| 61 | <p> |
| 62 | Added a new Developer Option to show memory state and application memory usage |
| 63 | ranked by how often they run and amount of memory consumed. |
| 64 | </p> |
| 65 | |
| 66 | <h3 id="opt-api">API</h3> |
| 67 | <p> |
| 68 | Added a new ActivityManager.isLowRamDevice() to allow applications to detect |
| 69 | when running on low memory devices and choose to disable large-RAM features. |
| 70 | </p> |
| 71 | |
| 72 | <h3 id="opt-track">Memory tracking</h3> |
| 73 | <p> |
| 74 | New memtrack HAL to track graphics memory allocations, additional information |
| 75 | in dumpsys meminfo, clarified summaries in meminfo (for example reported free |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 76 | RAM includes RAM of cached processes, so that OEMs don't try to optimize the |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 77 | wrong thing). |
| 78 | </p> |
| 79 | |
| 80 | <h2 id="build-time">Build-time configuration</h2> |
| 81 | <h3 id="flag">Enable Low Ram Device flag</h3> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 82 | <p>We are introducing a new API called |
| 83 | <code>ActivityManager.isLowRamDevice()</code> for applications to determine if |
| 84 | they should turn off specific memory-intensive |
Clay Murphy | 1606da4 | 2013-11-05 16:43:25 -0800 | [diff] [blame] | 85 | features that work poorly on low-memory devices.</p> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 86 | <p>For 512MB devices, this API is expected to return: "true" It can be enabled by |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 87 | the following system property in the device makefile.<br/> |
| 88 | <code>PRODUCT_PROPERTY_OVERRIDES += ro.config.low_ram=true</code></p> |
| 89 | |
| 90 | <h3 id="jit">Disable JIT</h3> |
| 91 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 92 | <p>System-wide JIT memory usage is dependent on the number of applications |
| 93 | running and the code footprint of those applications. The JIT establishes a |
| 94 | maximum translated code cache size and touches the pages within it as needed. |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 95 | JIT costs somewhere between 3M and 6M across a typical running system.<br/> |
| 96 | <br/> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 97 | The large apps tend to max out the code cache fairly quickly (which by default |
| 98 | has been 1M). On average, JIT cache usage runs somewhere between 100K and 200K |
| 99 | bytes per app. Reducing the max size of the cache can help somewhat with |
| 100 | memory usage, but if set too low will send the JIT into a thrashing mode. For |
| 101 | the really low-memory devices, we recommend the JIT be disabled entirely.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 102 | |
| 103 | <p>This can be achieved by adding the following line to the product makefile:<br/> |
| 104 | <code>PRODUCT_PROPERTY_OVERRIDES += dalvik.vm.jit.codecachesize=0</code></p> |
| 105 | <h3 id="launcher">Launcher Configs</h3> |
| 106 | |
| 107 | |
| 108 | <p>Ensure the default wallpaper setup on launcher is <strong>not</strong> |
Clay Murphy | 1606da4 | 2013-11-05 16:43:25 -0800 | [diff] [blame] | 109 | using live-wallpaper. Low-memory devices should not pre-install any live wallpapers. </p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 110 | |
| 111 | |
| 112 | <h2 id="kernel">Kernel configuration</h2> |
| 113 | <h3 id="kernel-tuning">Tuning kernel/ActivityManager to reduce direct reclaim </h3> |
| 114 | |
| 115 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 116 | <p>Direct reclaim happens when a process or the kernel tries to allocate a page |
| 117 | of memory (either directly or due to faulting in a new page) and the kernel |
| 118 | has used all available free memory. This requires the kernel to block the |
| 119 | allocation while it frees up a page. This in turn often requires disk I/O to |
| 120 | flush out a dirty file-backed page or waiting for <code>lowmemorykiller</code> to kill a |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 121 | process. This can result in extra I/O in any thread, including a UI thread.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 122 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 123 | <p>To avoid direct reclaim, the kernel has watermarks that trigger <code>kswapd</code> or |
| 124 | background reclaim. This is a thread that tries to free up pages so the next |
| 125 | time a real thread allocates it can succeed quickly.</p> |
| 126 | |
| 127 | <p>The default threshold to trigger background reclaim is fairly low, around 2MB |
| 128 | on a 2GB device and 636KB on a 512MB device. And the kernel reclaims only a |
| 129 | few MB of memory in background reclaim. This means any process that quickly |
| 130 | allocates more than a few megabytes is going to quickly hit direct reclaim.</p> |
| 131 | |
| 132 | <p>Support for a new kernel tunable is added in the android-3.4 kernel branch as |
| 133 | patch 92189d47f66c67e5fd92eafaa287e153197a454f ("add extra free kbytes |
| 134 | tunable"). Cherry-picking this patch to a device's kernel will allow |
| 135 | ActivityManager to tell the kernel to try to keep 3 full-screen 32 bpp buffers |
| 136 | of memory free.</p> |
| 137 | |
| 138 | <p>These thresholds can be configured via the framework config.xml</p> |
| 139 | |
| 140 | <pre> |
| 141 | <!-- Device configuration setting the /proc/sys/vm/extra_free_kbytes tunable |
| 142 | in the kernel (if it exists). A high value will increase the amount of memory |
| 143 | that the kernel tries to keep free, reducing allocation time and causing the |
| 144 | lowmemorykiller to kill earlier. A low value allows more memory to be used by |
| 145 | processes but may cause more allocations to block waiting on disk I/O or |
| 146 | lowmemorykiller. Overrides the default value chosen by ActivityManager based |
| 147 | on screen size. 0 prevents keeping any extra memory over what the kernel keeps |
| 148 | by default. -1 keeps the default. --> |
| 149 | <integer name="config_extraFreeKbytesAbsolute">-1</integer> |
| 150 | </pre> |
| 151 | |
| 152 | <pre> |
| 153 | <!-- Device configuration adjusting the /proc/sys/vm/extra_free_kbytes |
| 154 | tunable in the kernel (if it exists). 0 uses the default value chosen by |
| 155 | ActivityManager. A positive value will increase the amount of memory that the |
| 156 | kernel tries to keep free, reducing allocation time and causing the |
| 157 | lowmemorykiller to kill earlier. A negative value allows more memory to be |
| 158 | used by processes but may cause more allocations to block waiting on disk I/O |
| 159 | or lowmemorykiller. Directly added to the default value chosen by |
| 160 | ActivityManager based on screen size. --> |
| 161 | <integer name="config_extraFreeKbytesAdjust">0</integer> |
| 162 | </pre> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 163 | |
| 164 | <h3 id="lowmem">Tuning LowMemoryKiller</h3> |
| 165 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 166 | <p>ActivityManager configures the thresholds of the LowMemoryKiller to match its |
| 167 | expectation of the working set of file-backed pages (cached pages) required to |
| 168 | run the processes in each priority level bucket. If a device has high |
| 169 | requirements for the working set, for example if the vendor UI requires more |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 170 | memory or if more services have been added, the thresholds can be increased. </p> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 171 | |
| 172 | <p>The thresholds can be reduced if too much memory is being reserved for file |
| 173 | backed pages, so that background processes are being killed long before disk |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 174 | thrashing would occur due to the cache getting too small.</p> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 175 | |
| 176 | <pre> |
| 177 | <!-- Device configuration setting the minfree tunable in the lowmemorykiller |
| 178 | in the kernel. A high value will cause the lowmemorykiller to fire earlier, |
| 179 | keeping more memory in the file cache and preventing I/O thrashing, but |
| 180 | allowing fewer processes to stay in memory. A low value will keep more |
| 181 | processes in memory but may cause thrashing if set too low. Overrides the |
| 182 | default value chosen by ActivityManager based on screen size and total memory |
| 183 | for the largest lowmemorykiller bucket, and scaled proportionally to the |
| 184 | smaller buckets. -1 keeps the default. --> |
| 185 | <integer name="config_lowMemoryKillerMinFreeKbytesAbsolute">-1</integer> |
| 186 | </pre> |
| 187 | |
| 188 | <pre> |
| 189 | <!-- Device configuration adjusting the minfree tunable in the |
| 190 | lowmemorykiller in the kernel. A high value will cause the lowmemorykiller to |
| 191 | fire earlier, keeping more memory in the file cache and preventing I/O |
| 192 | thrashing, but allowing fewer processes to stay in memory. A low value will |
| 193 | keep more processes in memory but may cause thrashing if set too low. Directly |
| 194 | added to the default value chosen by ActivityManager based on screen |
| 195 | size and total memory for the largest lowmemorykiller bucket, and scaled |
| 196 | proportionally to the smaller buckets. 0 keeps the default. --> |
| 197 | <integer name="config_lowMemoryKillerMinFreeKbytesAdjust">0</integer> |
| 198 | </pre> |
| 199 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 200 | <h3 id="ksm">KSM (Kernel samepage merging)</h3> |
| 201 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 202 | <p>KSM is a kernel thread that runs in the background and compares pages in |
| 203 | memory that have been marked <code>MADV_MERGEABLE</code> by user-space. If two pages are |
| 204 | found to be the same, the KSM thread merges them back as a single |
| 205 | copy-on-write page of memory.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 206 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 207 | <p>KSM will save memory over time on a running system, gaining memory duplication |
| 208 | at a cost of CPU power, which could have an impact on battery life. You should |
| 209 | measure whether the power tradeoff is worth the memory savings you get by |
| 210 | enabling KSM.</p> |
| 211 | |
| 212 | <p>To test KSM, we recommend looking at long running devices (several hours) and |
| 213 | seeing whether KSM makes any noticeable improvement on launch times and |
| 214 | rendering times.</p> |
| 215 | |
| 216 | <p>To enable KSM, enable <code>CONFIG_KSM</code> in the kernel and then add the |
| 217 | following lines to your` <code>init.<device>.rc</code> file:<br> |
| 218 | |
| 219 | <pre> |
| 220 | write /sys/kernel/mm/ksm/pages_to_scan 100 |
| 221 | write /sys/kernel/mm/ksm/sleep_millisecs 500 |
| 222 | write /sys/kernel/mm/ksm/run 1 |
| 223 | </pre> |
| 224 | |
| 225 | <p>Once enabled, there are few utilities that will help in the debugging namely : |
| 226 | procrank, librank, & ksminfo. These utilities allow you to see which KSM |
| 227 | memory is mapped to what process, which processes use the most KSM memory. |
| 228 | Once you have found a chunk of memory that looks worth exploring you can use |
| 229 | either the hat utility if it's a duplicate object on the dalvik heap. </p> |
| 230 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 231 | <h3 id="zram">Swap to zRAM</h3> |
| 232 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 233 | <p>zRAM swap can increase the amount of memory available in the system by |
| 234 | compressing memory pages and putting them in a dynamically allocated swap area |
| 235 | of memory.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 236 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 237 | <p>Again, since this is trading off CPU time for a small increase in memory, you |
| 238 | should be careful about measuring the performance impact zRAM swap has on your |
| 239 | system.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 240 | |
| 241 | <p>Android handles swap to zRAM at several levels:</p> |
| 242 | |
| 243 | <ul> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 244 | <li>First, the following kernel options must be enabled to use zRAM swap |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 245 | effectively: |
| 246 | <ul> |
| 247 | <li><code>CONFIG_SWAP</code></li> |
| 248 | <li><code>CONFIG_CGROUP_MEM_RES_CTLR</code></li> |
| 249 | <li><code>CONFIG_CGROUP_MEM_RES_CTLR_SWAP</code></li> |
| 250 | <li><code>CONFIG_ZRAM</code></li> |
| 251 | </ul> |
| 252 | </li> |
| 253 | <li>Then, you should add a line that looks like this to your fstab:<br /> |
| 254 | <code>/dev/block/zram0 none swap defaults zramsize=<size in bytes>,swapprio=<swap partition priority></code><br /> |
| 255 | <code><br /> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 256 | zramsize</code> is mandatory and indicates how much uncompressed memory you want |
| 257 | the zram area to hold. Compression ratios in the 30-50% range are usually |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 258 | observed.<br /> |
| 259 | <br /> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 260 | <code>swapprio</code> is optional and not needed if you don't have more than one swap |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 261 | area.<br /> |
| 262 | <br /> |
dcashman | fcc4543 | 2015-12-08 14:08:58 -0800 | [diff] [blame] | 263 | You should also be sure to label the associated block device as a swap_block_device |
| 264 | in the device-specific <a href="{@docRoot}security/selinux/implement.html"> |
| 265 | sepolicy/file_contexts</a> so that it is treated properly by SELinux. <br /> |
| 266 | <code>/dev/block/zram0 u:object_r:swap_block_device:s0</code><br /> |
| 267 | <br /> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 268 | </li> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 269 | <li>By default, the Linux kernel swaps in 8 pages of memory at a time. When |
| 270 | using ZRAM, the incremental cost of reading 1 page at a time is negligible |
| 271 | and may help in case the device is under extreme memory pressure. To read |
| 272 | only 1 page at a time, add the following to your <code>init.rc</code>:<br /> |
| 273 | <code>write /proc/sys/vm/page-cluster 0</code></li> |
| 274 | <li>In your <code>init.rc</code> after the <code>mount_all /fstab.X</code> line, add:<br /> |
| 275 | <code>swapon_all /fstab.X</code></li> |
| 276 | <li>The memory cgroups are automatically configured at boot time if the |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 277 | feature is enabled in kernel.</li> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 278 | <li>If memory cgroups are available, the ActivityManager will mark lower |
| 279 | priority threads as being more swappable than other threads. If memory is |
| 280 | needed, the Android kernel will start migrating memory pages to zRAM swap, |
| 281 | giving a higher priority to those memory pages that have been marked by |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 282 | ActivityManager. </li> |
| 283 | </ul> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 284 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 285 | <h3 id="carveouts">Carveouts, Ion and Contiguous Memory Allocation (CMA)</h3> |
| 286 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 287 | <p>It is especially important on low memory devices to be mindful about |
| 288 | carveouts, especially those that will not always be fully utilized -- for |
| 289 | example a carveout for secure video playback. There are several solutions to |
| 290 | minimizing the impact of your carveout regions that depend on the exact |
| 291 | requirements of your hardware.</p> |
| 292 | |
| 293 | <p>If hardware permits discontiguous memory allocations, the ion system heap |
| 294 | allows memory allocations from system memory, |
| 295 | eliminating the need for a carveout. It also attempts to make large |
| 296 | allocations to eliminate TLB pressure on peripherals. If memory regions must |
| 297 | be contiguous or confined to a specific address range, the contiguous memory |
| 298 | allocator (CMA) can be used.</p> |
| 299 | |
| 300 | <p>This creates a carveout that the system can also use of for movable pages. |
| 301 | When the region is needed, movable pages will be migrated out of it, allowing |
| 302 | the system to use a large carveout for other purposes when it is free. CMA can |
| 303 | be used directly or more simply via ion by using the ion cma heap.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 304 | |
| 305 | <h2 id="app-opts">Application optimization tips</h2> |
| 306 | <ul> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 307 | <li>Review <a |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 308 | href="http://developer.android.com/training/articles/memory.html">Managing your |
| 309 | App's Memory</a> and these past blog posts on the same topic: |
| 310 | <ul> |
| 311 | <li><a |
| 312 | href="http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html">http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html</a></li> |
| 313 | <li><a |
| 314 | href="http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html">http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html</a></li> |
| 315 | <li><a |
| 316 | href="http://android-developers.blogspot.com/2009/02/track-memory-allocations.html">http://android-developers.blogspot.com/2009/02/track-memory-allocations.html</a></li> |
| 317 | <li> <a |
| 318 | href="http://tools.android.com/recent/lintperformancechecks">http://tools.android.com/recent/lintperformancechecks</a></li> |
| 319 | </ul> |
| 320 | </li> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 321 | <li>Check/remove any unused assets from preinstalled apps - |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 322 | development/tools/findunused (should help make the app smaller).</li> |
| 323 | <li>Use PNG format for assets, especially when they have transparent areas</li> |
| 324 | <li>If writing native code, use calloc() rather than malloc/memset</li> |
| 325 | <li>Don't enable code that is writing Parcel data to disk and reading it later.</li> |
| 326 | <li>Don't subscribe to every package installed, instead use ssp filtering. Add |
| 327 | filtering like below: |
| 328 | <br /> |
| 329 | <code><data android:scheme="package" android:ssp="com.android.pkg1" /><br /> |
| 330 | <data android:scheme="package" android:ssp="com.myapp.act1" /></code></li> |
| 331 | </ul> |
| 332 | |
| 333 | <h3 id="process-states">Understand the various process states in Android</h3> |
| 334 | |
| 335 | <ul> |
| 336 | <li><p>SERVICE - SERVICE_RESTARTING<br/> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 337 | Applications that are making themselves run in the background for their own |
| 338 | reason. Most common problem apps have when they run in the background too |
| 339 | much. %duration * pss is probably a good "badness" metric, although this set |
| 340 | is so focused that just doing %duration is probably better to focus on the |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 341 | fact that we just don't want them running at all.</p></li> |
| 342 | <li><p>IMPORTANT_FOREGROUND - RECEIVER<br/> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 343 | Applications running in the background (not directly interacting with the |
| 344 | user) for any reason. These all add memory load to the system. In this case |
| 345 | the (%duration * pss) badness value is probably the best ordering of such |
| 346 | processes, because many of these will be always running for good reason, and |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 347 | their pss size then is very important as part of their memory load.</p></li> |
| 348 | <li><p>PERSISTENT<br/> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 349 | Persistent system processes. Track pss to watch for these processes getting |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 350 | too large.</p></li> |
| 351 | <li><p>TOP<br/> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 352 | Process the user is currently interacting with. Again, pss is the important |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 353 | metric here, showing how much memory load the app is creating while in use.</p></li> |
| 354 | <li><p>HOME - CACHED_EMPTY<br/> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 355 | All of these processes at the bottom are ones that the system is keeping |
| 356 | around in case they are needed again; but they can be freely killed at any |
| 357 | time and re-created if needed. These are the basis for how we compute the |
| 358 | memory state -- normal, moderate, low, critical is based on how many of these |
| 359 | processes the system can keep around. Again the key thing for these processes |
| 360 | is the pss; these processes should try to get their memory footprint down as |
| 361 | much as possible when they are in this state, to allow for the maximum total |
| 362 | number of processes to be kept around. Generally a well behaved app will have |
| 363 | a pss footprint that is significantly smaller when in this state than when |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 364 | TOP.</p></li> |
| 365 | <li> |
| 366 | <p>TOP vs. CACHED_ACTIVITY-CACHED_ACTIVITY_CLIENT<em><br/> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 367 | </em>The difference in pss between when a process is TOP vs. when it is in either |
| 368 | of these specific cached states is the best data for seeing how well it is |
| 369 | releasing memory when going into the background. Excluding CACHED_EMPTY state |
| 370 | makes this data better, since it removes situations when the process has |
| 371 | started for some reasons besides doing UI and so will not have to deal with |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 372 | all of the UI overhead it gets when interacting with the user.</p></li> |
| 373 | </ul> |
| 374 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 375 | <h2 id="analysis">Analysis</h2> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 376 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 377 | <h3 id="app-startup">Analyzing app startup time</h3> |
| 378 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 379 | <p>Use <code>$ adb shell am start</code> with the <code>-P</code> or |
| 380 | <code>--start-profiler</code> option to run the profiler when your app starts. |
| 381 | This will start the profiler almost immediately after your process is forked |
| 382 | from zygote, before any of your code is loaded into it.</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 383 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 384 | <h3 id="bug-reports">Analyze using bugreports </h3> |
| 385 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 386 | <p>Now contains various information that can be used for debugging. The |
| 387 | services include <code>batterystats</code>, <code>netstats</code>, |
| 388 | <code>procstats</code>, and <code>usagestats</code>. You can find them with |
| 389 | lines like this:</p> |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 390 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 391 | <pre> |
| 392 | ------ CHECKIN BATTERYSTATS (dumpsys batterystats --checkin) ------ |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 393 | 7,0,h,-2558644,97,1946288161,3,2,0,340,4183 |
| 394 | 7,0,h,-2553041,97,1946288161,3,2,0,340,4183 |
| 395 | </pre> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 396 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 397 | <h3 id="persistent">Check for any persistent processes</h3> |
| 398 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 399 | <p>Reboot the device and check the processes.<br/> |
| 400 | Run for a few hours and check the processes again. There should not be any |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 401 | long running processes.</p> |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 402 | |
Clay Murphy | 66f1c56 | 2013-10-28 10:32:50 -0700 | [diff] [blame] | 403 | <h3 id="longevity">Run longevity tests</h3> |
| 404 | |
Clay Murphy | cfc1872 | 2015-12-11 16:16:20 -0800 | [diff] [blame] | 405 | <p>Run for longer durations and track the memory of the process. Does it |
| 406 | increase? Does it stay constant? Create Canonical use cases and run longevity |
| 407 | tests on these scenarios</p> |