Moved memory snapshot samples over from glitch

This commit is contained in:
Patrick Brosset 2022-01-19 15:55:29 +01:00
Родитель 5194c5eb7d
Коммит d57d45701a
11 изменённых файлов: 412 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,3 @@
# Record heap snapshots in DevTools
This is the source code for the demo pages used in the Microsoft Edge DevTools tutorial: [Record heap snapshots](https://docs.microsoft.com/microsoft-edge/devtools-guide-chromium/memory-problems/heap-snapshots).

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Example 3</title>
</head>
<body>
<h1>Example 3</h1>
<h2>Example 3: Scattered objects</h2>
<p><button onclick="init()">Create scattered objects</button></p>
<script src="example-03.js"></script>
<p>Take a heap snapshot and watch the objects (Item) allocations.</p>
<hr />
<iframe src="example-03.js"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,22 @@
function Item(x) {
this.x = x;
}
function numbers() {
var result = new Array(10000);
for (var i = 0, l = result.length; i < l; ++i) result[i] = new Item(i);
return new Item(result);
}
function strings() {
var result = new Array(10000);
for (var i = 0, l = result.length; i < l; ++i)
result[i] = new Item(i.toString());
return new Item(result);
}
function init() {
numberCache = numbers();
stringCache = strings();
documentCache = new Item(document.body.textContent.toLowerCase());
}

Просмотреть файл

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<title>Example 6</title>
</head>
<body>
<h1>Example 6</h1>
<h2>Example 6: Leaking DOM nodes</h2>
<p>
If the compiler uses hidden classes, your code runs MUCH faster and uses
MUCH LESS memory.
</p>
<ol>
<li>Open Timeline tab.</li>
<li>Start recording activity.</li>
<li>
Repeat the next steps and watch the Timeline
<ol>
<li>Create some nodes</li>
<li>GC</li>
</ol>
</li>
</ol>
<p>
<button onclick="createNodes()">
Create nodes (some of them leaked)
</button>
</p>
<script src="example-06.js"></script>
<hr />
<iframe src="example-06.js"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,32 @@
"use strict";
var leakedNodes = [];
function createNode(text) {
var div = document.createElement("div"),
innerDiv = document.createElement("div"),
buf;
buf = document.createTextNode(text + " - " + new Date().toTimeString());
innerDiv.appendChild(buf);
div.appendChild(innerDiv);
return div;
}
function createLeakedNodes() {
var i;
for (i = 0; i < 20; i++) {
leakedNodes.push(createNode("Leaked:" + i));
}
}
function createGCNodes() {
var i;
for (i = 0; i < 20; i++) {
createNode("Collected:" + i);
}
}
function createNodes() {
createLeakedNodes();
createGCNodes();
}

Просмотреть файл

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Example 7</title>
</head>
<body>
<!DOCTYPE html>
<h1>Example 7</h1>
<h2>Example 7: Eval is evil (almost always)</h2>
<p>Analyze the impact of closures on memory</p>
<p>
See that <code>eval</code> retains a reference on all the variables of the
closure.
</p>
<ol>
<li>Start the creation of new closures</li>
<li>Take a heap snapshot</li>
<li>
Find the closures (named <code>lC</code>, <code>sC</code>, and
<code>eC</code>)
</li>
</ol>
<p>
<button onclick="largeClosures()">
Closures maintain hold on large string
</button>
</p>
<p>
<button onclick="smallClosures()">
Closures maintain hold only on small strings
</button>
</p>
<p>
<button onclick="evalClosures()">Closures with <code>eval</code></button>
</p>
<p><button onclick="stopAndClear()">Stop and clear</button></p>
<script src="example-07.js"></script>
<hr />
<iframe src="example-07.js"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,81 @@
"use strict";
var intervalId,
closures = [];
function createLargeClosure() {
var largeStr = new Array(1000000).join("x");
return function lC() {
// this IS a named function
return largeStr;
};
}
function createLargeClosureUnnamed() {
var largeStr = new Array(1000000).join("x");
return function() {
// this IS NOT a named function
return largeStr;
};
}
function createSmallClosure() {
var smallStr = "x";
var largeStr = new Array(1000000).join("x");
return function sC() {
return smallStr;
};
}
function createEvalClosure() {
var smallStr = "x";
var largeStr = new Array(1000000).join("x");
return function eC() {
eval("");
return smallStr;
};
}
function largeClosures() {
stopInterval();
intervalId = setInterval(function() {
closures.push(createLargeClosure());
}, 1000);
}
function largeClosuresUnnamed() {
stopInterval();
intervalId = setInterval(function() {
closures.push(createLargeClosureUnnamed());
}, 1000);
}
function smallClosures() {
stopInterval();
intervalId = setInterval(function() {
closures.push(createSmallClosure());
}, 1000);
}
function evalClosures() {
stopInterval();
intervalId = setInterval(function() {
closures.push(createEvalClosure());
}, 1000);
}
function stopInterval() {
if (intervalId) {
clearInterval(intervalId);
}
intervalId = null;
}
function clear() {
closures.length = 0;
}
function stopAndClear() {
stopInterval();
clear();
}

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Example 8</title>
</head>
<body>
<h1>Example 8</h1>
<h2>Example 8: Recording heap allocations</h2>
<p>Analyze the impact of closures on memory</p>
<p>
See that <code>eval</code> retains a reference on all the variables of the
closure.
</p>
<ol>
<li>Start to record heap allocations</li>
<li>Start the creation of new closures</li>
<li>Analyze what happens</li>
</ol>
<p>
<button onclick="largeClosures()">
Closures maintain hold on large string
</button>
</p>
<p>
<button onclick="smallClosures()">
Closures maintain hold only on small strings
</button>
</p>
<p>
<button onclick="evalClosures()">Closures with <code>eval</code></button>
</p>
<p><button onclick="stopAndClear()">Stop and clear</button></p>
<script src="example-08.js"></script>
<hr />
<iframe src="example-08.js"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,65 @@
"use strict";
var intervalId,
closures = [];
function createLargeClosure() {
var largeStr = new Array(1000000).join("x");
return function lC() {
return largeStr;
};
}
function createSmallClosure() {
var smallStr = "x";
var largeStr = new Array(1000000).join("x");
return function sC() {
return smallStr;
};
}
function createEvalClosure() {
var smallStr = "x";
var largeStr = new Array(1000000).join("x");
return function eC() {
eval("");
return smallStr;
};
}
function largeClosures() {
stopInterval();
intervalId = setInterval(function() {
closures.push(createLargeClosure());
}, 1000);
}
function smallClosures() {
stopInterval();
intervalId = setInterval(function() {
closures.push(createSmallClosure());
}, 1000);
}
function evalClosures() {
stopInterval();
intervalId = setInterval(function() {
closures.push(createEvalClosure());
}, 1000);
}
function stopInterval() {
if (intervalId) {
clearInterval(intervalId);
}
intervalId = null;
}
function clear() {
closures.length = 0;
}
function stopAndClear() {
stopInterval();
clear();
}

Просмотреть файл

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>Example 9</title>
</head>
<body>
<h1>Example 9</h1>
<h2>Example 9: DOM leaks bigger than expected</h2>
<ol>
<li>Start memory profiling. Watch node count.</li>
<li>
Create a subtree of dom nodes and save a reference to a leaf and subtree
route
</li>
<li>Detach tree</li>
<li>Watch the detached node count</li>
<li>Remove tree reference</li>
<li>Watch the detached node count</li>
<li>Remove leaf reference</li>
<li>Watch the detached node count</li>
</ol>
<p><button onclick="createTree()">Create tree</button></p>
<p><button onclick="detachTree()">Detach tree</button></p>
<p>
<button onclick="removeTreeReference()">Remove tree reference</button>
</p>
<p>
<button onclick="removeLeafReference()">Remove leaf reference</button>
</p>
<script src="example-09.js"></script>
<hr />
<iframe src="example-09.js"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,49 @@
"use strict";
var leakedNodes = [],
parentDiv,
leaf,
counter = 0;
function createLeaf() {
counter++;
var div = document.createElement("div");
div.appendChild(document.createTextNode("Leaf " + counter));
div.someText = new Array(1e6).join("x");
return div;
}
function createBranch(number) {
var div = document.createElement("div");
createNodesAndReturnLastLeaf(div, number - 1);
return div;
}
function createNodesAndReturnLastLeaf(parentDiv, number) {
var i, lastLeaf;
for (i = 0; i < number; i++) {
parentDiv.appendChild(createBranch(number));
}
for (i = 0; i < number; i++) {
parentDiv.appendChild((lastLeaf = createLeaf(number, i)));
}
return lastLeaf;
}
function createTree() {
parentDiv = document.createElement("div");
leaf = createNodesAndReturnLastLeaf(parentDiv, 4);
document.body.appendChild(parentDiv);
}
function detachTree() {
document.body.removeChild(parentDiv);
}
function removeTreeReference() {
parentDiv = null;
}
function removeLeafReference() {
leaf = null;
}