dart-sdk/runtime/tools/heapsnapshot
Konstantin Shcheglov b7d3c47d13 Adds benchmark measuring memory consumption of live objects after analyzing flutter.
Will warm up the memory cache and then measure how much live memory the analyzer consumes after visiting all elements with the warmed up cache.

All results
--------------------------------
flutter_elements
  reachableObjects
    count: 9071480
    size: 799672175 = 780929 KB = 762 MB
  _SimpleUri
    count: 3112
    size(shallow): 248960 = 243 KB
    duplicateCount: 0

Change-Id: I75209f88f6f615172127cd439afe9d0cd83b1c4f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/329682
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
2023-10-10 17:54:08 +00:00
..
bin [vm] Heap snapshot tool can load file from arguments 2022-12-15 12:31:45 +00:00
lib/src Adds benchmark measuring memory consumption of live objects after analyzing flutter. 2023-10-10 17:54:08 +00:00
test Adds benchmark measuring memory consumption of live objects after analyzing flutter. 2023-10-10 17:54:08 +00:00
CHANGELOG.md
pubspec.yaml Adds benchmark measuring memory consumption of live objects after analyzing flutter. 2023-10-10 17:54:08 +00:00
README.md Update README.md 2023-04-25 18:50:20 +00:00

Obtaining a heapsnapshot

There's several ways one can obtain a heapsnapshot

Obtain snapshot from live VM

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.

Programmatically

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');
  ...
}

CLI Usage:

Loading a snapshot

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>

Finding all live objects

# Find all live objects by finding transitive closure of roots.
# We assign to a `all` variable for later usage.
all = closure roots

Show known sets of objects

# Show named sets / known variables
info

Show statistics of objects

To examine how many objects there are per class and how large they are one can use the stats command:

stats all

Example usage session

# 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