dart-sdk/runtime/tools/heapsnapshot
Konstantin Shcheglov 895540889e Update SDK constraints for SDK packages.
https://dart-review.googlesource.com/c/sdk/+/287660 implements it.
I want to fix pre-existing violations before enabling.

Bug: https://github.com/dart-lang/sdk/issues/34978
Change-Id: Ie7731162c643018a2312b265f444bc00534c0a51
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/287664
Reviewed-by: Leon Senft <leonsenft@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
2023-03-09 19:52:47 +00:00
..
bin [vm] Heap snapshot tool can load file from arguments 2022-12-15 12:31:45 +00:00
lib Support external typed data in heapsnapshot analysis tool 2023-02-21 12:58:34 +00:00
test Support external typed data in heapsnapshot analysis tool 2023-02-21 12:58:34 +00:00
CHANGELOG.md
pubspec.yaml Update SDK constraints for SDK packages. 2023-03-09 19:52:47 +00:00
README.md Make runtime/tools/heapsnapshot/README.md more elaborate 2023-01-19 13:12:02 +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

It's possible to programmatically dump a heapsnapshot to a file by using a (currently) internal API:

import 'dart:_internal';

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.
  VMInternalsForTesting.writeHeapSnapshotToFile('dump.heapsnapshot');
  ...
}

In order to be able to import dart:_internal, one has to update the VMTarget class:

class VMTarget extends Target {
  ...
  bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) => true;
  ...
}

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