Clay Murphy | 87d3bb5 | 2016-07-08 12:03:55 -0700 | [diff] [blame] | 1 | page.title=Implementing ART Just-In-Time (JIT) Compiler |
| 2 | @jd:body |
| 3 | |
| 4 | <!-- |
| 5 | Copyright 2016 The Android Open Source Project |
| 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 | |
| 20 | |
| 21 | <div id="qv-wrapper"> |
| 22 | <div id="qv"> |
| 23 | <h2 id="Contents">In this document</h2> |
| 24 | <ol id="auto-toc"> |
| 25 | </ol> |
| 26 | </div> |
| 27 | </div> |
| 28 | |
| 29 | <p> |
| 30 | Android N adds a just-in-time (JIT) compiler with code profiling to Android |
| 31 | runtime (ART) that constantly improves the performance of Android apps as they |
| 32 | run. The JIT compiler complements ART's current ahead-of-time (AOT) compiler and |
| 33 | improves runtime performance, saves storage space, and speeds app updates and |
| 34 | system updates. |
| 35 | </p> |
| 36 | |
| 37 | <p> |
| 38 | The JIT compiler also improves upon the AOT compiler by avoiding system slowdown |
| 39 | during automatic application updates or recompilation of applications during |
| 40 | OTAs. This feature should require minimal device integration on the part of |
| 41 | manufacturers. |
| 42 | </p> |
| 43 | |
| 44 | <p> |
| 45 | JIT and AOT use the same compiler with an almost identical set of optimizations. |
| 46 | The generated code might not be the same but it depends. JIT makes uses of |
| 47 | runtime type information and can do better inlining. Also, with JIT we sometimes |
| 48 | do OSR compilation (on stack replacement) which will again generate a bit |
| 49 | different code. |
| 50 | </p> |
| 51 | |
| 52 | <p> |
| 53 | See <a |
| 54 | href="https://developer.android.com/preview/api-overview.html#jit_aot">Profile-guided |
| 55 | JIT/AOT Compilation</a> on developer.android.com for a more thorough overview. |
| 56 | </p> |
| 57 | |
| 58 | <h2 id="architectural-overview">Architectural Overview</h2> |
| 59 | |
| 60 | <img src="images/jit-arch.png" alt="JIT architecture" width="633" id="JIT-architecture" /> |
| 61 | <p class="img-caption"> |
| 62 | <strong>Figure 1.</strong> JIT architecture - how it works |
| 63 | </p> |
| 64 | |
| 65 | <h2 id="flow">Flow</h2> |
| 66 | |
| 67 | <p> |
| 68 | JIT compilation works in this manner: |
| 69 | </p> |
| 70 | |
| 71 | <ol> |
| 72 | <li>The user runs the app, which then triggers ART to load the .dex file. |
| 73 | <li>If the .oat file (the AOT binary for the .dex file) is available, ART uses |
| 74 | them directly. Note that .oat files are generated regularly. However, that does |
| 75 | not imply they contain compiled code (AOT binary). |
| 76 | <li>If no .oat file is available, ART runs through either JIT or an interpreter |
| 77 | to execute the .dex file. ART will always use the .oat files if available. |
| 78 | Otherwise, it will use the APK and extract it in memory to get to the .dex |
| 79 | incurring a big memory overhead (equal to the size of the dex files). |
| 80 | <li>JIT is enabled for any application that is not compiled according to the |
| 81 | "speed" compilation filter (which says, compile as much as you can from the |
| 82 | app). |
| 83 | <li>The JIT profile data is dumped to a file in a system directory. Only the |
| 84 | application has access to the directory. |
| 85 | <li>The AOT compilation (dex2oat) daemon parses that file to drive its |
| 86 | compilation.</li> |
| 87 | </ol> |
| 88 | |
| 89 | <img src="images/jit-profile-comp.png" alt="Profile-guided comp" width="452" id="JIT-profile-comp" /> |
| 90 | <p class="img-caption"> |
| 91 | <strong>Figure 2.</strong> Profile-guided compilation |
| 92 | </p> |
| 93 | |
| 94 | <img src="images/jit-daemon.png" alt="JIT daemon" width="718" id="JIT-daemon" /> |
| 95 | <p class="img-caption"> |
| 96 | <strong>Figure 3.</strong> How the daemon works |
| 97 | </p> |
| 98 | |
| 99 | <p> |
| 100 | The Google Play service is an example used by other apps. These application tend |
| 101 | to behave more like shared libraries. |
| 102 | </p> |
| 103 | |
| 104 | <h2 id="jit-workflow">JIT Workflow</h2> |
| 105 | <p> |
| 106 | See the following high-level overview of how JIT works in the next diagram. |
| 107 | </p> |
| 108 | |
| 109 | <img src="images/jit-workflow.png" alt="JIT architecture" width="707" id="JIT-workflow" /> |
| 110 | <p class="img-caption"> |
| 111 | <strong>Figure 4.</strong> JIT data flow |
| 112 | </p> |
| 113 | |
| 114 | <p> |
| 115 | This means: |
| 116 | </p> |
| 117 | |
| 118 | <ul> |
| 119 | <li>Profiling information is stored in the code cache and subjected to garbage |
| 120 | collection under memory pressure. |
| 121 | <li>As a result, there’s no guarantee the snapshot taken when the application is |
| 122 | in the background will contain the complete data (i.e. everything that was |
| 123 | JITed). |
| 124 | <li>There is no attempt to make sure we record everything as that will impact |
| 125 | runtime performance. |
| 126 | <li>Methods can be in three different states: <ul> |
| 127 | <li>interpreted (dex code) |
| 128 | <li>JIT compiled |
| 129 | <li>AOT compiled |
| 130 | <li>If both, JIT and AOT code exists (e.g. due to repeated de-optimizations), |
| 131 | the JITed code will be preferred. |
| 132 | <li>The memory requirement to run JIT without impacting foreground app |
| 133 | performance depends upon the app in question. Large apps will require more |
| 134 | memory than small apps. In general, big apps stabilize around 4 MB.</li></ul> |
| 135 | </li> |
| 136 | </ul> |
| 137 | |
| 138 | <h2 id="system-properties">System Properties</h2> |
| 139 | |
| 140 | <p> |
| 141 | These system properties control JIT behavior: |
| 142 | </p><ul> |
| 143 | <li><code>dalvik.vm.usejit <true|false></code> - Whether or not the JIT is |
| 144 | enabled. |
| 145 | <li><code>dalvik.vm.jitinitialsize</code> (default 64K) - The initial capacity |
| 146 | of the code cache. The code cache will regularly GC and increase if needed. It |
| 147 | is possible to view the size of the code cache for your app with:<br> |
| 148 | <code> $ adb shell dumpsys meminfo -d <pid></code> |
| 149 | <li><code>dalvik.vm.jitmaxsize</code> (default 64M) - The maximum capacity of |
| 150 | the code cache. |
| 151 | <li><code>dalvik.vm.jitthreshold <integer></code> (default 10000) - This |
| 152 | is the threshold that the "hotness" counter of a method needs to pass in order |
| 153 | for the method to be JIT compiled. The "hotness" counter is a metric internal |
| 154 | to the runtime. It includes the number of calls, backward branches & other |
| 155 | factors. |
| 156 | <li><code>dalvik.vm.usejitprofiles <true|false></code> - Whether or not |
| 157 | JIT profiles are enabled; this may be used even if usejit is false. |
| 158 | <li><code>dalvik.vm.jitprithreadweight <integer></code> (default to |
| 159 | <code>dalvik.vm.jitthreshold</code> / 20) - The weight of the JIT "samples" |
| 160 | (see jitthreshold) for the application UI thread. Use to speed up compilation |
| 161 | of methods that directly affect users experience when interacting with the |
| 162 | app. |
| 163 | <li><code>dalvik.vm.jittransitionweight <integer></code> |
| 164 | (<code>dalvik.vm.jitthreshold</code> / 10) - The weight of the method |
| 165 | invocation that transitions between compile code and interpreter. This helps |
| 166 | make sure the methods involved are compiled to minimize transitions (which are |
| 167 | expensive). |
| 168 | </li> |
| 169 | </ul> |
| 170 | |
| 171 | <h2 id="tuning">Tuning</h2> |
| 172 | |
| 173 | <p> |
| 174 | Partners may precompile (some of) the system apps if they want so. Initial JIT |
| 175 | performance vs pre-compiled depends on the the app, but in general they are |
| 176 | quite close. It might be worth noting that precompiled apps will not be profiled |
| 177 | and as such will take more space and may miss on other optimizations. |
| 178 | </p> |
| 179 | |
| 180 | <p> |
| 181 | In Android N, there's a generic way to specify the level of |
| 182 | compilation/verification based on the different use cases. For example, the |
| 183 | default option for install time is to do only verification (and postpone |
| 184 | compilation to a later stage). The compilation levels can be configured via |
| 185 | system properties with the defaults being: |
| 186 | </p> |
| 187 | |
| 188 | <pre> |
| 189 | pm.dexopt.install=interpret-only |
| 190 | pm.dexopt.bg-dexopt=speed-profile |
| 191 | pm.dexopt.ab-ota=speed-profile |
| 192 | pm.dexopt.nsys-library=speed |
| 193 | pm.dexopt.shared-apk=speed |
| 194 | pm.dexopt.forced-dexopt=speed |
| 195 | pm.dexopt.core-app=speed |
| 196 | pm.dexopt.first-boot=interpret-only |
| 197 | pm.dexopt.boot=verify-profile |
| 198 | </pre> |
| 199 | |
| 200 | <p> |
| 201 | Note the reference to A/B over-the-air (OTA) updates here. |
| 202 | </p> |
| 203 | |
| 204 | <p> |
| 205 | Check <code>$ adb shell cmd package compile</code> for usage. Note all commands |
| 206 | are preceded by a dollar ($) sign that should be excluded when copying and |
| 207 | pasting. A few common use cases: |
| 208 | </p> |
| 209 | |
| 210 | <h3 id="turn-on-jit-logging">Turn on JIT logging</h3> |
| 211 | |
| 212 | <pre> |
| 213 | $ adb root |
| 214 | $ adb shell stop |
| 215 | $ adb shell setprop dalvik.vm.extra-opts -verbose:jit |
| 216 | $ adb shell start |
| 217 | </pre> |
| 218 | |
| 219 | <h3 id="disable-jit-and-run-applications-in-interpreter">Disable JIT</h3> |
| 220 | |
| 221 | <pre> |
| 222 | $ adb root |
| 223 | $ adb shell stop |
| 224 | $ adb shell setprop dalvik.vm.usejit false |
| 225 | $ adb shell start |
| 226 | </pre> |
| 227 | |
| 228 | <h3 id="force-compilation-of-a-specific-package">Force compilation of a specific |
| 229 | package</h3> |
| 230 | |
| 231 | <ul> |
| 232 | <li>Profile-based: |
| 233 | <code>$ adb shell cmd package compile -m speed-profile -f |
| 234 | my-package</code> |
| 235 | <li>Full: |
| 236 | <code>$ adb shell cmd package compile -m speed -f |
| 237 | my-package</code></li> |
| 238 | </ul> |
| 239 | |
| 240 | <h3 id="force-compilation-of-all-packages">Force compilation of all |
| 241 | packages</h3> |
| 242 | |
| 243 | <ul> |
| 244 | <li>Profile-based: |
| 245 | <code>$ adb shell cmd package compile -m speed-profile -f |
| 246 | -a</code> |
| 247 | <li>Full: |
| 248 | <code>$ adb shell cmd package compile -m speed -f -a</code></li></ul> |
| 249 | |
| 250 | <h3 id="clear-profile-data-and-remove-compiled-code">Clear profile data and |
| 251 | remove compiled code</h3> |
| 252 | |
| 253 | <ul> |
| 254 | <li>One package: |
| 255 | <code>$ adb shell cmd package compile --reset my-package</code> |
| 256 | <li>All packages |
| 257 | <code>$ adb shell cmd package compile --reset |
| 258 | -a</code></li> |
| 259 | </ul> |
| 260 | |
| 261 | <h2 id="validation">Validation</h2> |
| 262 | |
| 263 | <p> |
| 264 | To ensure their version of the feature works as intended, partners should run |
| 265 | the ART test in <code>android/art/test</code>. Also, see the CTS test |
| 266 | <code>hostsidetests/compilation</code> for userdedug builds. |
| 267 | </p> |