Update 13-Oct-2015:The Deep Memory Profiler tools (dmprof) were not maintained, became non-functional, and were removed from the codebase . See issue 490464. IntroductionDeep Memory Profiler (dmprof) is a 1) whole-process, 2) timeline-based and 3) post-mortem memory profiler for Chromium. It's designed to categorize all memory usage in a process without any omission. See the Design Doc if interested. Memory bloat has been a serious issue in Chromium for years. Bloat is harder to fix than leak and errors. We have memory checkers like Valgrind and Address Sanitizer for leak and errors, but no handy tools for bloat. Dmprof is an easy-to-use tool for bloat to know “who is the memory eater”. (It would be helpful also for leak.) AnnouncementFuture announcements (e.g. command line changes) will be done in dmprof@chromium.org. Subscribe it if you're interested.
Sub-profilers
How to UseDmprof profiles memory usage post-mortem. You need to 1) get memory dumps while Chrome is running, and then 2) analyze the dumps. The analyzing script dmprof is available in src/tools/deep_memory_profiler of the Chromium source tree, or can be retrieved by downloading and running download.sh. Phase 1: Build ChromiumYou can use dmprof for Chromium static builds with some build options both for Release and Debug builds. Note that it is not available for shared builds. Linux and ChromeOS-Chrome
AndroidBe careful not to overwrite GYP_DEFINES predefined by env_setup.sh.
ChromeOS / ChromiumOS
Phase 2: Run ChromiumRemember the Process ID of your target process! (c.f. about:memory)Linux and ChromeOS-ChromeRun Chromium with a command-line option --no-sandbox and the following environment variables:
Android# NOTE: the device needs to be rooted! adb shell mkdir -p /data/local/tmp/heap adb shell chmod 0777 /data/local/tmp/heap # Set the following system properties adb shell setprop heapprof /data/local/tmp/heap/dumptestadb shell setprop heapprof.mmap 1 adb shell setprop heapprof.deep_heap_profile 1 adb shell setprop heapprof.time_interval 10 ChromeOS / ChromiumOSPrepare a file /var/tmp/deep_memory_profiler_prefix.txt in your device or VM image. Its content should just have a prefix to dumped files /path/to/prefix like: /var/tmp/heapprof
If you get dumps from a standalone Chromium process periodically, prepare a file /var/tmp/deep_memory_profiler_time_interval.txt which contains just an integer meaning the interval time to dump: 60 Phase 3: Make Chromium dumpStandalone (automatic periodical dump)If you specified "time interval" described above, the Chromium process dumps heap profiles periodically. It depends on the platform how to specify "time interval". WebDriver (ChromeDriver)A WebDriver (ChromeDriver) API function is available to dump. Try dump_heap_profile():
Memory Benchmarking V8 APIYou can dump heap profiles manually from DevTools (or automatically with your script) when you set the environment variables above and specify the command line option --enable-memory-benchmarking to Chrome. chrome.memoryBenchmarking.heapProfilerDump("browser" or "renderer", "some reason") TelemetryYou can use a Telemetry profiler to drive chrome and, if running on android, to also fetch the files from the device. It utilizes the above Memory Benchmarking V8 API internally. See Telemetry instructions. Phase 4: Get the dumpsFind the dumps at /path/to/prefix.*.heap as specified above. Names of the dumps include Process IDs. For example, prefix.12345.0002.heap for pid = 12345. '0002' is a sequence number of the dump. The dmprof analyzer script (in the Phase 5) needs the executed Chrome binary to extract symbols. If you analyze in the same host with the Chrome process, you don't need special things. If you analyze in a different host from the Chrome process (it's common in Android and ChromeOS), you may need to specify the path to the executed Chrome binary on the host. (See Phase 5 for details.) Linux and ChromeOS-ChromeHeap profiles are dumped to the directory where you specified in the environment variable HEAPPROFILE. AndroidHeap profiles are dumped in the device directory where you specified in the property heapprof. Fetch the dump from the device to your host by the following command. adb pull /data/local/tmp/heap/ . The dmprof script guesses the path of the Chrome binary on the host if the executed binary was in an Android-specific directory (e.g. /data/app-lib/). If the guess fails, use --alternative-dirs for the dmprof script (in the Phase 5). ChromeOS / ChromiumOSHeap profiles are dumped in the device directory where you specified in /var/tmp/deep_memory_profiler_prefix.txt. Fetch them in a certain way like scp from the device / VM. The dmprof script doesn't know where is the Chrome binary on the host. Use --alternative-dirs for the dmprof script (in the Phase 5). Phase 5: Analyze the dumpsUse the dmprof script to analyze with the dumped heap profiles.
$ dmprof csv dmprof.03511.0001.heap > dmprof.03511.result.csv Or, use this to generate a local html with a graph and a data table: # Generate a JSON output for your dumps.
$ tools/deep_memory_profiler/dmprof json /path/to/first-one-of-the-dumps.heap > FOO.json # Convert the JSON file to a HTML file. $ tools/deep_memory_profiler/graph.py FOO.json > graph.html In case of Android or ChromeOS, you may need to use --alternative-dirs for the dmprof script to specify the path of the Chrome binary on the host instead of the path on the device. Android$ dmprof csv --alternative-dirs=/data/app-lib/com.google.android.apps.chrome-1@/home/self/chrome/src/out/Release/lib dmprof.03511.0001.heap
Assuming /data/app-lib/com.google.android.apps.chrome-1 on device as /home/self/chrome/src/out/Release/lib on host ... ChromeOS / ChromiumOS$ dmprof csv --alternative-dirs=/opt/google/chrome@/home/self/chromeos/chroot/build/x86-generic/opt/google/chrome dmprof.03511.0001.heap
Assuming /opt/google/chrome on device as /home/self/chromeos/chroot/build/x86-generic/opt/google/chrome on host ... Phase 6: Drill down into components / backtracesGiven a specific component listed in the graph above, sue the following command to
# HEAP_FILE => TCMalloc .heap file
|
mustbezero & unhooked-absent | Should be zero. |
unhooked-anonymous | VMA is mapped, but no information is recorded. No label is given in /proc/.../maps. |
unhooked-file-exec | VMA is mapped, but no information is recorded. An executable file is mapped. |
unhooked-file-nonexec | VMA is mapped, but no information is recorded. A non-executable file is mapped. |
unhooked-file-stack | VMA is mapped, but no information is recorded. Used as a stack. |
unhooked-other | VMA is mapped, but no information is recorded. Used for other purposes. |
no-bucket | Should be small. Out of record because it is an ignorable small blocks. |
tc-unused | Reserved by TCMalloc, but not used by malloc(). Headers, fragmentation and free-list. |
mmap-v8 | mmap'ed for V8. It includes JavaScript heaps and JIT compiled code. |
mmap-catch-all | mmap'ed for other purposes. |
tc-used-all | All memory blocks allocated by malloc(). |
mmap-v8-heap-newspace | JavaScript new (nursery) heap for younger objects. |
mmap-v8-heap-coderange | Code produced at runtime including JIT-compiled JavaScript code. |
mmap-v8-heap-pagedspace | JavaScript old heap and many other object spaces. |
mmap-v8-other | Other regions mmap'ed by V8. |
mmap-catch-all | Any other mmap'ed regions. |
tc-v8 | Blocks allocated from V8. |
tc-skia | Blocks allocated from Skia. |
tc-webkit-catch-all | Blocks allocated from WebKit. |
tc-unknown-string | Blocks which are related to std::string. |
tc-catch-all | Any other blocks allocated by malloc(). |
mmap-v8-heap-newspace | JavaScript new (nursery) heap for younger objects. |
mmap-v8-heap-coderange | Code produced at runtime including JIT-compiled JavaScript code. |
mmap-v8-heap-pagedspace | JavaScript old heap and many other spaces. |
mmap-v8-other | Other regions mmap'ed by V8. |
mmap-catch-all | Any other mmap'ed regions. |
tc-webcore-fontcache | Blocks used for FontCache. |
tc-skia | Blocks used for Skia. |
tc-renderobject | Blocks used for RenderObject. |
tc-renderstyle | Blocks used for RenderStyle. |
tc-webcore-sharedbuf | Blocks used for WebCore's SharedBuffer. |
tc-webcore-XHRcreate | Blocks used for WebCore's XMLHttpRequest (create). |
tc-webcore-XHRreceived | Blocks used for WebCore's XMLHttpRequest (received). |
tc-webcore-docwriter-add | Blocks used for WebCore's DocumentWriter. |
tc-webcore-node-and-doc | Blocks used for WebCore's HTMLElement, Text, and other Node objects. |
tc-webcore-node-factory | Blocks created by WebCore's HTML*Factory. |
tc-webcore-element-wrapper | Blocks created by WebCore's createHTML*ElementWrapper. |
tc-webcore-stylepropertyset | Blocks used for WebCore's StylePropertySet (CSS). |
tc-webcore-style-createsheet | Blocks created by WebCore's StyleElement::createSheet. |
tc-webcore-cachedresource | Blocks used for WebCore's CachedResource. |
tc-webcore-script-execute | Blocks created by WebCore's ScriptElement::execute. |
tc-webcore-events-related | Blocks related to WebCore's events (EventListener and so on) |
tc-webcore-document-write | Blocks created by WebCore's Document::write. |
tc-webcore-node-create-renderer | Blocks created by WebCore's Node::createRendererIfNeeded. |
tc-webcore-render-catch-all | Any other blocks related to WebCore's Render. |
tc-webcore-setInnerHTML-except-node | Blocks created by setInnerHTML. |
tc-wtf-StringImpl-user-catch-all | Blocks used for WTF::StringImpl. |
tc-wtf-HashTable-user-catch-all | Blocks used for WTF::HashTable. |
tc-webcore-everything-create | Blocks created by WebCore's any create() method. |
tc-webkit-from-v8-catch-all | Blocks created by V8 via WebKit functions. |
tc-webkit-catch-all | Any other blocks created by WebKit. |
tc-v8-catch-all | Any other blocks created in V8. |
tc-toplevel-string | All std::string objects created at the top-level. |
tc-catch-all | Any other blocks by malloc(). |
mmap-v8 | mmap'ed for V8. It includes JavaScript heaps and JIT compiled code. |
mmap-catch-all | mmap'ed for other purposes. |
tc-std-string | std::string objects. |
tc-WTF-String | WTF::String objects. |
tc-no-typeinfo-StringImpl | No type_info (not allocated by 'new'), but allocated for StringImpl. |
tc-Skia | Skia objects. |
tc-WebCore-Style | WebCore's style objects. |
tc-no-typeinfo-other | Any other blocks without type_info. |
tc-other | All objects with other type_info. |