接口:IHeapSnapshot
堆快照通常是一个图,其中图节点是 JS 堆对象,图边是 JS 堆对象之间的 JS 引用。 有关堆图中节点和边的结构的更多详细信息,请查看 IHeapNode 和 IHeapEdge。
属性
edges: IHeapEdges
一个伪数组,包含所有堆图边(对堆中堆对象的引用)。 一个 JS 堆可能包含数百万个引用,因此 memlab 使用伪数组作为所有堆边的集合。 该伪数组提供 API 来查询和遍历所有堆引用。
- 示例:
import type {IHeapSnapshot, IHeapEdge} from '@memlab/core';
import {dumpNodeHeapSnapshot} from '@memlab/core';
import {getFullHeapFromFile} from '@memlab/heap-analysis';
(async function () {
const heapFile = dumpNodeHeapSnapshot();
const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
// get the total number of heap references
heap.edges.length;
heap.edges.forEach((edge: IHeapEdge) => {
// traverse each reference in the heap
});
})();
nodes: IHeapNodes
一个伪数组,包含所有堆图节点(堆中的 JS 对象)。 一个 JS 堆可能包含数百万个堆对象,因此 memlab 使用伪数组作为所有堆对象的集合。 该伪数组提供 API 来查询和遍历所有堆对象。
- 示例:
import type {IHeapSnapshot, IHeapNode} from '@memlab/core';
import {dumpNodeHeapSnapshot} from '@memlab/core';
import {getFullHeapFromFile} from '@memlab/heap-analysis';
(async function () {
const heapFile = dumpNodeHeapSnapshot();
const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
// get the total number of heap objects
heap.nodes.length;
heap.nodes.forEach((node: IHeapNode) => {
// traverse each heap object
});
})();
方法
getAnyObjectWithClassName(className
)
搜索堆,并获取具有指定构造函数名称的 JS 对象实例之一(如果存在)。
import type {IHeapSnapshot} from '@memlab/core';
import {takeNodeMinimalHeap} from '@memlab/core';
class TestObject {
public arr1 = [1, 2, 3];
public arr2 = ['1', '2', '3'];
}
(async function () {
const obj = new TestObject();
// get a heap snapshot of the current program state
const heap: IHeapSnapshot = await takeNodeMinimalHeap();
const node = heap.getAnyObjectWithClassName('TestObject');
console.log(node?.name); // should be 'TestObject'
})();
getNodeById(id
)
如果您具有堆节点(堆中的 JS 对象)的 ID,请使用此 API 获取与该 ID 关联的 IHeapNode。
import type {IHeapSnapshot} from '@memlab/core';
import {dumpNodeHeapSnapshot} from '@memlab/core';
import {getFullHeapFromFile} from '@memlab/heap-analysis';
(async function () {
const heapFile = dumpNodeHeapSnapshot();
const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
const node = heap.getNodeById(351);
node?.id; // should be 351
})();
getNodesByIdSet(ids
)
给定一组堆节点(堆中的 JS 对象)的 ID,请使用此 API 获取这些堆节点的集合。
参数:
ids
:Set
<number
>| 您要查询的堆节点(堆中的 JS 对象)的 ID 集合
返回:
Set
<IHeapNode
>| 这些堆节点的集合。 该集合将仅包含在堆中找到的节点。 如果未找到任何输入 ID,则此 API 将返回一个空集合。示例:
import type {IHeapSnapshot} from '@memlab/core';
import {dumpNodeHeapSnapshot} from '@memlab/core';
import {getFullHeapFromFile} from '@memlab/heap-analysis';
(async function () {
const heapFile = dumpNodeHeapSnapshot();
const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
// suppose 1000 is not a valid id in the heap
const set = heap.getNodesByIdSet(new Set([1, 2, 1000, 3]));
set // should be Set([node1, node2, node3])
})();
getNodesByIds(ids
)
给定一个堆节点(堆中的 JS 对象)的 ID 数组,请使用此 API 获取这些堆节点的数组。
参数:
ids
:number
[] | 您要查询的堆节点(堆中的 JS 对象)的 ID 数组
返回:
Nullable
<IHeapNode
>[] | 这些堆节点的数组。 返回数组将保留输入数组的顺序。 如果在堆中找不到 ID,则返回数组中对应的元素将为null
。示例:
import type {IHeapSnapshot} from '@memlab/core';
import {dumpNodeHeapSnapshot} from '@memlab/core';
import {getFullHeapFromFile} from '@memlab/heap-analysis';
(async function () {
const heapFile = dumpNodeHeapSnapshot();
const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
// suppose 1000 is not a valid id in the heap
const nodes = heap.getNodesByIds([1, 2, 1000, 3]);
nodes // should be [node1, node2, null, node3]
})();
hasObjectWithClassName(className
)
搜索堆,并检查是否存在具有指定构造函数名称的任何 JS 对象实例。
参数:
className
:string
| 对象实例的构造函数名称
返回:
boolean
| 如果堆中至少存在一个这样的对象,则返回true
示例:您可以编写带有内存断言的 jest 单元测试
// save as example.test.ts
import type {IHeapSnapshot, Nullable} from '@memlab/core';
import {config, takeNodeMinimalHeap} from '@memlab/core';
class TestObject {
public arr1 = [1, 2, 3];
public arr2 = ['1', '2', '3'];
}
test('memory test with heap assertion', async () => {
config.muteConsole = true; // no console output
let obj: Nullable<TestObject> = new TestObject();
// get a heap snapshot of the current program state
let heap: IHeapSnapshot = await takeNodeMinimalHeap();
// call some function that may add references to obj
rabbitHole(obj)
expect(heap.hasObjectWithClassName('TestObject')).toBe(true);
obj = null;
heap = await takeNodeMinimalHeap();
// if rabbitHole does not have any side effect that
// adds new references to obj, then obj can be GCed
expect(heap.hasObjectWithClassName('TestObject')).toBe(false);
}, 30000);
hasObjectWithPropertyName(nameOrIndex
)
搜索堆,并检查是否存在具有指定属性名称的任何 JS 对象实例。
参数:
nameOrIndex
:string
|number
| 对象实例上的属性名称(字符串)或元素索引(数字)
返回:
boolean
| 如果堆中至少存在一个这样的对象,则返回true
示例:
import type {IHeapSnapshot} from '@memlab/core';
import {dumpNodeHeapSnapshot} from '@memlab/core';
import {getFullHeapFromFile} from '@memlab/heap-analysis';
(async function () {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const object = {'memlab-test-heap-property': 'memlab-test-heap-value'};
const heapFile = dumpNodeHeapSnapshot();
const heap: IHeapSnapshot = await getFullHeapFromFile(heapFile);
// should be true
console.log(heap.hasObjectWithPropertyName('memlab-test-heap-property'));
})();
hasObjectWithTag(tag
)
搜索堆,并检查是否存在由 tagObject 标记的任何 JS 对象实例。
tagObject
API 不以任何方式修改对象实例(例如,没有添加到标记对象的额外或隐藏属性)。
- 参数:
tag
:string
| 由 tagObject 标记的对象实例上的标记名称
- 返回:
boolean
| 如果堆中至少存在一个这样的对象,则返回true
import type {IHeapSnapshot, AnyValue} from '@memlab/core';
import {config, takeNodeMinimalHeap, tagObject} from '@memlab/core';
test('memory test', async () => {
config.muteConsole = true;
const o1: AnyValue = {};
let o2: AnyValue = {};
// tag o1 with marker: "memlab-mark-1", does not modify o1 in any way
tagObject(o1, 'memlab-mark-1');
// tag o2 with marker: "memlab-mark-2", does not modify o2 in any way
tagObject(o2, 'memlab-mark-2');
o2 = null;
const heap: IHeapSnapshot = await takeNodeMinimalHeap();
// expect object with marker "memlab-mark-1" exists
expect(heap.hasObjectWithTag('memlab-mark-1')).toBe(true);
// expect object with marker "memlab-mark-2" can be GCed
expect(heap.hasObjectWithTag('memlab-mark-2')).toBe(false);
}, 30000);