There's several ways one can obtain a heapsnapshot
One can use existing tools (e.g. observatory / DevTools) to load & save a heapsnapshot.
For convenience there's also a bin/download.dart
script in package:heapsnapshot
that can be given an URL to a live VM and it will fetch a heapsnapshot.
Note: enabled for debug and release Dart build modes, but not for product mode.
It's possible to programmatically dump a heapsnapshot to a file by using a dart:developer
API:
import 'dart:developer'; foo() { ... // Will dump the heapsnapshot at a specific place in program execution. // Allows very precise analysis of what data is live at a particular place. NativeRuntime.writeHeapSnapshotToFile('dump.heapsnapshot'); ... }
After launching bin/explore.dart
one has to load a heapsnapshot before doing anything else. This can be done with the load
command. It will auto-complete directories and any file with the .heapsnapshot
extension.
# Load load <file>
# Find all live objects by finding transitive closure of roots. # We assign to a `all` variable for later usage. all = closure roots
# Show named sets / known variables info
To examine how many objects there are per class and how large they are one can use the stats
command:
stats all
# Filter lists from "all" into "lists" lists = filter all _List # Find empty lists into "empty-lists" empty-lists = dfilter lists ==0 # Who's using the empty lists? users empty-lists # print that info (from $0 in this case as we didn't give it a name but it was # the first one we didn't give a name) stat $0 # Filter more empty-growable-lists = filter (users empty-lists) _GrowableList # Print stats empty-growable-lists # Who's using them? retainers empty-growable-lists # Look into strings next strings = filter all String # What's inside the strings dstats strings # Who's pointing to the big strings? retainers (dfilter strings >=1024) # Small strings small-strings = dfilter strings <100 # See them dstats small-strings # Who's retaining the string "foo" f = dfilter small-strings foo retainters f # Find stuff with specific field hasField = filter all :specificField stats closure hasField :specificField foo = follow hasField :specificField stats closure foo # Stop the closure search if going into specific files stats closure foo ^file1.dart ^file2.dart ^file3.dart