DevTools: Show number of JS VMs (aka isolates) in the live heap profiles
It is still an experimental feature.
Change-Id: I493cd634635612d785bc7f22a4e5e68d4c3c7c7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1601675
Commit-Queue: Alexei Filippov <[email protected]>
Reviewed-by: Dmitry Gozman <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#657966}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: a9acb82a157b6d7ce2bc1e1e86d7030cef26fcd7
diff --git a/front_end/profiler/LiveHeapProfileView.js b/front_end/profiler/LiveHeapProfileView.js
index 4aca1ce..12ee406 100644
--- a/front_end/profiler/LiveHeapProfileView.js
+++ b/front_end/profiler/LiveHeapProfileView.js
@@ -21,6 +21,7 @@
align: DataGrid.DataGrid.Align.Right,
sort: DataGrid.DataGrid.Order.Descending
},
+ {id: 'isolates', title: ls`VMs`, width: '40px', fixedWidth: true, align: DataGrid.DataGrid.Align.Right},
{id: 'url', title: ls`Script URL`, fixedWidth: false, sortable: true}
];
this._dataGrid = new DataGrid.SortableDataGrid(columns);
@@ -50,39 +51,43 @@
async _poll() {
const pollId = this._currentPollId;
do {
- const models = SDK.targetManager.models(SDK.HeapProfilerModel);
- const profiles = await Promise.all(models.map(model => model.getSamplingProfile()));
+ const isolates = Array.from(SDK.isolateManager.isolates());
+ const profiles = await Promise.all(
+ isolates.map(isolate => isolate.heapProfilerModel() && isolate.heapProfilerModel().getSamplingProfile()));
if (this._currentPollId !== pollId)
return;
- profiles.remove(null);
- this._update(profiles);
+ this._update(isolates, profiles);
await new Promise(r => setTimeout(r, 3000));
} while (this._currentPollId === pollId);
}
/**
- * @param {!Array<!Protocol.HeapProfiler.SamplingHeapProfile>} profiles
+ * @param {!Array<!SDK.IsolateManager.Isolate>} isolates
+ * @param {!Array<?Protocol.HeapProfiler.SamplingHeapProfile>} profiles
*/
- _update(profiles) {
- /** @type {!Map<string, number>} */
- const sizeByUrl = new Map();
- for (const profile of profiles)
- processNode('', profile.head);
+ _update(isolates, profiles) {
+ /** @type {!Map<string, !{size: number, isolates: !Set<!SDK.IsolateManager.Isolate>}>} */
+ const dataByUrl = new Map();
+ profiles.forEach((profile, index) => {
+ if (profile)
+ processNodeTree(isolates[index], '', profile.head);
+ });
const rootNode = this._dataGrid.rootNode();
const exisitingNodes = new Set();
- for (const pair of sizeByUrl) {
+ for (const pair of dataByUrl) {
const url = /** @type {string} */ (pair[0]);
- const size = /** @type {number} */ (pair[1]);
+ const size = /** @type {number} */ (pair[1].size);
+ const isolateCount = /** @type {number} */ (pair[1].isolates.size);
if (!url) {
console.info(`Node with empty URL: ${size} bytes`); // eslint-disable-line no-console
continue;
}
let node = this._gridNodeByUrl.get(url);
if (node) {
- node.updateSize(size);
+ node.updateNode(size, isolateCount);
} else {
- node = new Profiler.LiveHeapProfileView.GridNode(url, size);
+ node = new Profiler.LiveHeapProfileView.GridNode(url, size, isolateCount);
this._gridNodeByUrl.set(url, node);
rootNode.appendChild(node);
}
@@ -98,14 +103,22 @@
this._sortingChanged();
/**
+ * @param {!SDK.IsolateManager.Isolate} isolate
* @param {string} parentUrl
* @param {!Protocol.HeapProfiler.SamplingHeapProfileNode} node
*/
- function processNode(parentUrl, node) {
+ function processNodeTree(isolate, parentUrl, node) {
const url = node.callFrame.url || parentUrl || systemNodeName(node) || anonymousScriptName(node);
- if (node.selfSize)
- sizeByUrl.set(url, (sizeByUrl.get(url) || 0) + node.selfSize);
- node.children.forEach(child => processNode(url, child));
+ node.children.forEach(processNodeTree.bind(null, isolate, url));
+ if (!node.selfSize)
+ return;
+ let data = dataByUrl.get(url);
+ if (!data) {
+ data = {size: 0, isolates: new Set()};
+ dataByUrl.set(url, data);
+ }
+ data.size += node.selfSize;
+ data.isolates.add(isolate);
}
/**
@@ -160,20 +173,24 @@
/**
* @param {string} url
* @param {number} size
+ * @param {number} isolateCount
*/
- constructor(url, size) {
+ constructor(url, size, isolateCount) {
super();
this._url = url;
this._size = size;
+ this._isolateCount = isolateCount;
}
/**
* @param {number} size
+ * @param {number} isolateCount
*/
- updateSize(size) {
- if (this._size === size)
+ updateNode(size, isolateCount) {
+ if (this._size === size && this._isolateCount === isolateCount)
return;
this._size = size;
+ this._isolateCount = isolateCount;
this.refresh();
}
@@ -186,13 +203,15 @@
const cell = this.createTD(columnId);
switch (columnId) {
case 'url':
- cell.title = this._url;
cell.textContent = this._url;
break;
case 'size':
cell.textContent = Number.withThousandsSeparator(Math.round(this._size / 1e3));
cell.createChild('span', 'size-units').textContent = ls`KB`;
break;
+ case 'isolates':
+ cell.textContent = this._isolateCount;
+ break;
}
return cell;
}