зеркало из https://github.com/MicrosoftEdge/Demos.git
Moved memory snapshot samples over from glitch
This commit is contained in:
Родитель
5194c5eb7d
Коммит
d57d45701a
|
@ -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;
|
||||
}
|
Загрузка…
Ссылка в новой задаче