Home | History | Annotate | Download | only in docs
      1 <html>
      2 <head>
      3     <title>Dalvik Heap Profiling</title>
      4 </head>
      5 
      6 <body>
      7 <h1>Dalvik Heap Profiling</h1>
      8 
      9 <p>
     10 The Dalvik virtual machine can produce a complete dump of the contents
     11 of the virtual heap.  This is very useful for debugging memory usage
     12 and looking for memory leaks.  Getting at the information can be tricky,
     13 but has become easier in recent releases.
     14 </p><p>
     15 In what follows, the version number refers to the software release
     16 running on the phone.  To take advantage of the DDMS integration, you will
     17 also need a sufficiently recent version of DDMS.
     18 
     19 
     20 <h2>Getting the data</h2>
     21 <p>
     22 The first step is to cause the VM to dump its status, and then pull the hprof
     23 data off.  The exact manner for doing so has changed over time.
     24 </p><p>
     25 There is a <code>runhat</code> shell function, added by
     26 <code>build/envsetup.sh</code>, that partially automates these steps.  The
     27 function changes in each release to accommodate newer behavior, so you have
     28 to be careful that you don't use the wrong version.
     29 </p><p>
     30 
     31 <h3>Early releases (1.0/1.1)</h3>
     32 <p>
     33 You can only generate heap data on the emulator or a device with root
     34 access, because of the way the dump is initiated and where the output
     35 files go.
     36 </p><p>
     37 Get a command shell on the device:
     38 <blockquote><pre>
     39 $ adb shell
     40 </pre></blockquote>
     41 </p><p>
     42 You can verify that you're running as root with the <code>id</code> command.
     43 The response should look like <code>uid=0(root) gid=0(root)</code>.  If not,
     44 type <code>su</code> and try again.  If <code>su</code> fails, you're out
     45 of luck.
     46 
     47 </p><p>
     48 Next, ensure the target directory exists:
     49 <blockquote><pre>
     50 # mkdir /data/misc
     51 # chmod 777 /data/misc
     52 </pre></blockquote>
     53 
     54 </p><p>
     55 Use <code>ps</code> or DDMS to determine the process ID of your application,
     56 then send a <code>SIGUSR1</code> to the target process:
     57 
     58 <blockquote><pre>
     59 # kill -10 &lt;pid&gt;
     60 </pre></blockquote>
     61 
     62 </p><p>
     63 The signal causes a GC, followed by the heap dump (to be completely
     64 accurate, they actually happen concurrently, but the results in the heap
     65 dump reflect the post-GC state).  This can take a couple of seconds,
     66 so you have to watch for the GC log message to know when it's complete.
     67 </p><p>
     68 Next:
     69 
     70 <blockquote><pre>
     71 # ls /data/misc/heap-dump*
     72 # exit
     73 </pre></blockquote>
     74 
     75 </p><p>
     76 Use <code>ls</code> to check the file names, then <code>exit</code> to quit
     77 the device command shell.
     78 
     79 </p><p>
     80 You should see two output files, named
     81 <code>/data/misc/heap-dump-BLAH-BLAH.hprof</code> and
     82 <code>.hprof-head</code>, where BLAH is a runtime-generated value
     83 that ensures the filename is unique.  Pull them off of the device and
     84 remove the device-side copy:
     85 
     86 <blockquote><pre>
     87 $ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof tail.hprof
     88 $ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof-head head.hprof
     89 $ adb shell rm /data/misc/heap-dump-BLAH-BLAH.hprof /data/misc/heap-dump-BLAH-BLAH.hprof-head
     90 </pre></blockquote>
     91 
     92 </p><p>
     93 Merge them together and remove the intermediates:
     94 
     95 <blockquote><pre>
     96 $ cat head.hprof tail.hprof &gt; dump.hprof
     97 $ rm head.hprof tail.hprof
     98 </pre></blockquote>
     99 
    100 </p><p>
    101 You now have the hprof dump in <code>dump.hprof</code>.
    102 </p><p>
    103 
    104 
    105 <h3>Android 1.5 ("Cupcake")</h3>
    106 <p>
    107 Some steps were taken to make this simpler.  Notably, the two output
    108 files are now combined for you, and a new API call was added that allows
    109 a program to write the dump at will to a specific file.  If you're not
    110 using the API call, you still need to be on an emulator or running as root.
    111 (For some builds, you can use <code>adb root</code> to restart the adb
    112 daemon as root.)
    113 </p><p>
    114 The basic procedure is the same as for 1.0/1.1, but only one file will
    115 appear in <code>/data/misc</code> (no <code>-head</code>), and upon
    116 completion you will see a log message that says "hprof: heap dump completed".
    117 It looks like this in the log:
    118 
    119 <blockquote><pre>
    120 I/dalvikvm(  289): threadid=7: reacting to signal 10
    121 I/dalvikvm(  289): SIGUSR1 forcing GC and HPROF dump
    122 I/dalvikvm(  289): hprof: dumping VM heap to "/data/misc/heap-dump-tm1240861355-pid289.hprof-hptemp".
    123 I/dalvikvm(  289): hprof: dumping heap strings to "/data/misc/heap-dump-tm1240861355-pid289.hprof".
    124 I/dalvikvm(  289): hprof: heap dump completed, temp file removed
    125 </pre></blockquote>
    126 
    127 </p><p>
    128 Summary: as above, use <code>mkdir</code> and <code>chmod</code>
    129 to ensure the directory exists and is writable by your application.
    130 Send the <code>SIGUSR1</code> or use the API call to initiate a dump.
    131 Use <code>adb pull &lt;dump-file&gt;</code> and <code>adb shell rm
    132 &lt;dump-file&gt;</code> to retrieve the file and remove it from the
    133 device.  The concatenation step is not needed.
    134 
    135 </p><p>
    136 The new API is in the <code>android.os.Debug</code> class:
    137 <blockquote><pre>
    138 public static void dumpHprofData(String fileName) throws IOException
    139 </pre></blockquote>
    140 When called, the VM will go through the same series of steps (GC and
    141 generate a .hprof file), but the output will be written to a file of
    142 your choice, e.g. <code>/sdcard/myapp.hprof</code>.  Because you're
    143 initiating the action from within the app, and can write the file to
    144 removable storage or the app's private data area, you can do this on a
    145 device without root access.
    146 
    147 
    148 <h3>Android 1.6 ("Donut")</h3>
    149 <p>
    150 No real change to the way profiling works.
    151 However, 1.6 introduced the <code>WRITE_EXTERNAL_STORAGE</code>
    152 permission, which is required to write data to the SD card.  If you're
    153 accustomed to writing profile data to <code>/sdcard</code>, you will
    154 need to enable the permission in your application's manifest.
    155 </p>
    156 
    157 
    158 <h3>Android 2.0 ("Eclair")</h3>
    159 <p>
    160 In 2.0, features were added that allow DDMS to request a heap dump on
    161 demand, and automatically pull the result across.  Select your application
    162 and click the "dump HPROF file" button in the top left.  This always
    163 writes files to the SD card, so
    164 you must have a card inserted and the permission enabled in your application.
    165 </p>
    166 
    167 
    168 <h3>Android 2.2 ("Froyo")</h3>
    169 <p>
    170 DDMS heap dump requests are now streamed directly out of the VM, removing
    171 the external storage requirement.
    172 </p>
    173 
    174 <h3>Android 2.3 ("Gingerbread")</h3>
    175 <p>
    176 The <code>kill -10</code> (<code>SIGUSR1</code>) method of generating heap
    177 dumps has been removed from the VM.
    178 </p>
    179 
    180 <h3>Android 3.0 ("Honeycomb")</h3>
    181 <p>
    182 A new command-line tool has been added:
    183 </p>
    184 <blockquote><pre>am dumpheap &lt;pid&gt; &lt;output-file-name&gt;</pre></blockquote>
    185 <p>
    186 Unlike the <code>SIGUSR1</code> approach, this does not require a rooted
    187 phone.  It's only necessary for the application to be debuggable (by setting
    188 <code>android:debuggable="true"</code> in the <code>&lt;application&gt;</code>
    189 element of the app manifest).  The output file is opened by "am", which
    190 means you can write the data to a file on <code>/sdcard</code> without
    191 needing the <code>WRITE_EXTERNAL_STORAGE</code> permission in your app.
    192 <p>
    193 The <code>runhat</code> shell function has been updated to use this.
    194 </p>
    195 
    196 <h2>Examining the data</h2>
    197 <p>
    198 The data file format was augmented slightly from the common hprof format,
    199 and due to licensing restrictions the modified <code>hat</code> tool cannot
    200 be distributed.  A conversion tool, <code>hprof-conv</code>, can be used
    201 to strip the Android-specific portions from the output.  This tool was
    202 first included in 1.5, but will work with older versions of Android.
    203 </p><p>
    204 The converted output should work with any hprof data analyzer, including
    205 <code>jhat</code>, which is available for free in the Sun JDK, and
    206 Eclipse MAT.
    207 
    208 <!-- say something about how to track down common problems, interesting
    209      things to look for, ...? -->
    210 
    211 </p><p>
    212 <address>Copyright &copy; 2009 The Android Open Source Project</address>
    213 
    214 </body>
    215 </html>
    216