// language=HTML
const html = `
<!-- article out start -->
<article>
<!-- article in start -->
<h1>Lorem ipsum</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cumque, nostrum.</p>
<!-- article in end -->
</article>
<!-- article out end -->
<!-- article out start -->
<article>
<!-- article in start -->
<h1>Lorem ipsum</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cumque, nostrum.</p>
<!-- article in end -->
</article>
<!-- article out end -->
<!-- article out start -->
<article>
<!-- article in start -->
<h1>Lorem ipsum</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cumque, nostrum.</p>
<!-- article in end -->
</article>
<!-- article out end -->
`;
const template = document.createElement('template');
template.innerHTML = html;
window.testTemplate = template;
window.testTraverse = function traverse(node, use) {
if (!node) return;
use(node);
traverse(node.firstChild, use);
traverse(node.nextSibling, use);
}
const comments = [];
testTraverse(testTemplate.content.firstChild, node => {
if (node.nodeType === Node.COMMENT_NODE) {
comments.push(node);
}
});
const nodeIterator = document.createNodeIterator(
testTemplate.content,
NodeFilter.SHOW_ALL,
{
acceptNode(node) {
if (node.nodeType === Node.COMMENT_NODE) {
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_REJECT;
}
}
);
const comments = [];
while (nodeIterator.nextNode()) {
comments.push(nodeIterator.currentNode);
}
const nodeIterator = document.createNodeIterator(
testTemplate.content,
NodeFilter.SHOW_COMMENT
);
const comments = [];
while (nodeIterator.nextNode()) {
comments.push(nodeIterator.currentNode);
}
const treeWalker = document.createTreeWalker(
testTemplate.content,
NodeFilter.SHOW_ALL,
{
acceptNode(node) {
if (node.nodeType === Node.COMMENT_NODE) {
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_REJECT;
}
}
);
const comments = [];
while (treeWalker.nextNode()) {
comments.push(treeWalker.currentNode);
}
const treeWalker = document.createTreeWalker(
testTemplate.content,
NodeFilter.SHOW_COMMENT
);
const comments = [];
while (treeWalker.nextNode()) {
comments.push(treeWalker.currentNode);
}
const treeWalker = document.createTreeWalker(
testTemplate.content,
NodeFilter.SHOW_COMMENT
);
const comments = [];
let node;
while (node = treeWalker.nextNode()) {
if (node.nodeType === Node.COMMENT_NODE)
comments.push(node);
}
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
Traverse function | |
NodeIterator with filter function | |
NodeIterator with filter param | |
TreeWalker with filter function | |
TreeWalker with filter param | |
TreeWalker with manual filter |
Test name | Executions per second |
---|---|
Traverse function | 79054.7 Ops/sec |
NodeIterator with filter function | 10848.6 Ops/sec |
NodeIterator with filter param | 585815.9 Ops/sec |
TreeWalker with filter function | 30495.9 Ops/sec |
TreeWalker with filter param | 636782.2 Ops/sec |
TreeWalker with manual filter | 307164.8 Ops/sec |
Let's dive into the benchmark and explain what's being tested.
The benchmark is designed to compare the performance of four different ways to traverse a DOM tree: using a for
loop, NodeIterator
, TreeWalker
, and a manual filter with TreeWalker
. The goal is to identify which approach is the fastest.
Here's a brief overview of each method:
traverse
function that takes a node and an optional callback function as arguments. The function recursively traverses the DOM tree, calling the callback function on each node.NodeIterator
object that filters out nodes based on a provided function. The iterator is then used to traverse the DOM tree.TreeWalker
object that starts at the root of the DOM tree and walks down the tree, applying a filter function to each node. However, instead of using a callback function, it uses a manual loop to process the nodes.for
loop, it manually loops through the nodes and applies the filter.The benchmark measures the performance of each approach by executing each test 10 times and reporting the average number of executions per second (ExecutionsPerSecond) for each browser instance.
Now, let's analyze the results:
traverse
function.for
loop.Based on these results, it appears that using a custom iterator or walker with a filter function is generally faster than writing your own traversal logic using a for
loop. However, the performance difference between NodeIterator
and TreeWalker
is relatively small.