+2011-11-09 Adam Klein <adamk@chromium.org>
+
+ [MutationObservers] Microbenchmarks for appendChild, removeChild, and innerHTML
+ https://bugs.webkit.org/show_bug.cgi?id=71939
+
+ Reviewed by Ojan Vafai.
+
+ These benchmarks time both the DOM mutations themselves and the time taken
+ to call the MutationCallback. This measurement is achieved by
+ executing the code entirely within the MutationCallback itself.
+
+ * Mutation/append-child-deep.html: Added. Covers appendChild in a 200-node-deep tree with subtree observation.
+ * Mutation/append-child.html: Added. Covers appendChild in a flat tree.
+ * Mutation/inner-html.html: Added. Covers innerHTML adding and removing many nodes at a time.
+ * Mutation/remove-child-deep.html: Added. Covers removeChild in a 200-node-deep tree with subtree observation.
+ * Mutation/remove-child.html: Added. Covers removeChild in a flat tree.
+
2011-10-25 Adam Barth <abarth@webkit.org>
EventTargetFactory.in is not sorted
--- /dev/null
+<!DOCTYPE html>
+<body>
+<pre id="log"></pre>
+<script src="../Parser/resources/runner.js"></script>
+<div id="sandbox" style="display:none"></div>
+<script>
+var sandbox = document.getElementById('sandbox');
+var node = sandbox;
+for (var i = 0; i < 200; ++i)
+ node = node.appendChild(document.createElement('div'));
+var elems = [];
+for (var i = 0; i < 50000; ++i)
+ elems[i] = document.createElement('div');
+var observing = false;
+
+var observer = new WebKitMutationObserver(listener);
+var tickledSpan = document.createElement('span');
+observer.observe(tickledSpan, {attributes: true});
+
+function resetState() {
+ window.start = null;
+ window.numRuns = 25;
+ window.times = [];
+}
+
+function runAgain() {
+ tickledSpan.setAttribute('data-foo', numRuns);
+}
+
+function listener(mutations) {
+ if (start) {
+ var time = Date.now() - start;
+ times.push(time);
+ log(time);
+ }
+ if (numRuns-- >= 0) {
+ runAgain();
+ if (observing)
+ observer.disconnect()
+ node.innerHTML = '';
+ if (observing)
+ observer.observe(sandbox, {childList: true, subtree: true});
+ start = Date.now();
+ for (var i = 0; i < elems.length; ++i)
+ node.appendChild(elems[i]);
+ } else {
+ logStatistics(times);
+ if (!observing) {
+ observing = true;
+ resetState();
+ log('\n------------\n');
+ log('Running ' + numRuns + ' times with observation');
+ setTimeout(runAgain, 0);
+ }
+ }
+}
+
+resetState();
+log('Running ' + numRuns + ' times without observation');
+window.addEventListener('load', runAgain);
+</script>
+</body>
--- /dev/null
+<!DOCTYPE html>
+<body>
+<pre id="log"></pre>
+<script src="../Parser/resources/runner.js"></script>
+<div id="sandbox" style="display:none"></div>
+<script>
+var sandbox = document.getElementById('sandbox');
+var observing = false;
+
+var elems = [];
+for (var i = 0; i < 50000; ++i)
+ elems[i] = document.createElement('div');
+var observer = new WebKitMutationObserver(listener);
+var tickledSpan = document.createElement('span');
+observer.observe(tickledSpan, {attributes: true});
+
+function resetState() {
+ window.start = null;
+ window.numRuns = 25;
+ window.times = [];
+}
+
+function runAgain() {
+ tickledSpan.setAttribute('data-foo', numRuns);
+}
+
+function listener(mutations) {
+ if (start) {
+ var time = Date.now() - start;
+ times.push(time);
+ log(time);
+ }
+ if (numRuns-- >= 0) {
+ runAgain();
+ if (observing)
+ observer.disconnect()
+ sandbox.innerHTML = '';
+ if (observing)
+ observer.observe(sandbox, {childList: true});
+ start = Date.now();
+ for (var i = 0; i < elems.length; ++i)
+ sandbox.appendChild(elems[i]);
+ } else {
+ logStatistics(times);
+ if (!observing) {
+ observing = true;
+ resetState();
+ log('\n------------\n');
+ log('Running ' + numRuns + ' times with observation');
+ setTimeout(runAgain, 0);
+ }
+ }
+}
+
+resetState();
+log('Running ' + numRuns + ' times without observation');
+window.addEventListener('load', runAgain);
+</script>
+</body>
--- /dev/null
+<!DOCTYPE html>
+<body>
+<pre id="log"></pre>
+<script src="../Parser/resources/runner.js"></script>
+<div id="sandbox" style="display:none"></div>
+<script>
+var sandbox = document.getElementById('sandbox');
+var observing = false;
+for (var i = 0; i < 1000; ++i)
+ sandbox.appendChild(document.createElement('div'));
+var html = sandbox.innerHTML;
+
+var observer = new WebKitMutationObserver(listener);
+var tickledSpan = document.createElement('span');
+observer.observe(tickledSpan, {attributes: true});
+
+function resetState() {
+ window.start = null;
+ window.numRuns = 25;
+ window.times = [];
+}
+
+function runAgain() {
+ tickledSpan.setAttribute('data-foo', numRuns);
+}
+
+function listener(mutations) {
+ if (start) {
+ var time = Date.now() - start;
+ times.push(time);
+ log(time);
+ }
+ if (numRuns-- >= 0) {
+ runAgain();
+ start = Date.now();
+ for (var i = 0; i < 100; ++i)
+ sandbox.innerHTML = html;
+ } else {
+ logStatistics(times);
+ if (!observing) {
+ observer.observe(sandbox, {childList: true});
+ observing = true;
+ resetState();
+ log('\n------------\n');
+ log('Running ' + numRuns + ' times with observation');
+ setTimeout(runAgain, 0);
+ }
+ }
+}
+
+resetState();
+log('Running ' + numRuns + ' times without observation');
+window.addEventListener('load', runAgain);
+</script>
+</body>
--- /dev/null
+<!DOCTYPE html>
+<body>
+<pre id="log"></pre>
+<script src="../Parser/resources/runner.js"></script>
+<div id="sandbox" style="display:none"></div>
+<script>
+var sandbox = document.getElementById('sandbox');
+var node = sandbox;
+for (var i = 0; i < 200; ++i)
+ node = node.appendChild(document.createElement('div'));
+var observing = false;
+
+var observer = new WebKitMutationObserver(listener);
+var tickledSpan = document.createElement('span');
+observer.observe(tickledSpan, {attributes: true});
+
+function resetState() {
+ window.start = null;
+ window.numRuns = 25;
+ window.times = [];
+}
+
+function runAgain() {
+ tickledSpan.setAttribute('data-foo', numRuns);
+}
+
+function hideFromObservation(func) {
+ if (observing)
+ observer.disconnect();
+ func();
+ if (observing)
+ observer.observe(sandbox, {childList: true, subtree: true});
+}
+
+function listener(mutations) {
+ if (start) {
+ var time = Date.now() - start;
+ times.push(time);
+ log(time);
+ }
+ if (numRuns-- >= 0) {
+ runAgain();
+ hideFromObservation(function() {
+ for (var i = 0; i < 50000; ++i)
+ node.appendChild(document.createElement('div'));
+ });
+ start = Date.now();
+ while (node.firstChild)
+ node.removeChild(node.firstChild);
+ } else {
+ logStatistics(times);
+ if (!observing) {
+ observing = true;
+ resetState();
+ log('\n------------\n');
+ log('Running ' + numRuns + ' times with observation');
+ setTimeout(runAgain, 0);
+ }
+ }
+}
+
+resetState();
+log('Running ' + numRuns + ' times without observation');
+window.addEventListener('load', runAgain);
+</script>
+</body>
--- /dev/null
+<!DOCTYPE html>
+<body>
+<pre id="log"></pre>
+<script src="../Parser/resources/runner.js"></script>
+<div id="sandbox" style="display:none"></div>
+<script>
+var sandbox = document.getElementById('sandbox');
+var observing = false;
+
+var observer = new WebKitMutationObserver(listener);
+var tickledSpan = document.createElement('span');
+observer.observe(tickledSpan, {attributes: true});
+
+function resetState() {
+ window.start = null;
+ window.numRuns = 25;
+ window.times = [];
+}
+
+function runAgain() {
+ tickledSpan.setAttribute('data-foo', numRuns);
+}
+
+function hideFromObservation(func) {
+ if (observing)
+ observer.disconnect()
+ func();
+ if (observing)
+ observer.observe(sandbox, {childList: true});
+}
+
+function listener(mutations) {
+ if (start) {
+ var time = Date.now() - start;
+ times.push(time);
+ log(time);
+ }
+ if (numRuns-- >= 0) {
+ runAgain();
+ hideFromObservation(function() {
+ for (var i = 0; i < 50000; ++i)
+ sandbox.appendChild(document.createElement('div'));
+ });
+ start = Date.now();
+ while (sandbox.firstChild)
+ sandbox.removeChild(sandbox.firstChild);
+ } else {
+ logStatistics(times);
+ if (!observing) {
+ observer.observe(sandbox, {childList: true});
+ observing = true;
+ resetState();
+ log('\n------------\n');
+ log('Running ' + numRuns + ' times with observation');
+ setTimeout(runAgain, 0);
+ }
+ }
+}
+
+resetState();
+log('Running ' + numRuns + ' times without observation');
+window.addEventListener('load', runAgain);
+</script>
+</body>