Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

querySelectorAll vs NodeIterator vs TreeWalker - fastest pure JS flat DOM iterator [closed]

I'd like to flatten a DOM tree into an Array. The result should include the root as the first entry. Plain JS solution is preferred. What's the fastest way to achieve that?

HTML structure example:

<div class="tested-root">
    <span></span>
    <span></span>
    <div>
        <span></span>
        <span></span>
    </div>
    <div>
        <span></span>
        <span></span>
    </div>
</div>

The output expected to be: [div.tested-root, span, span, div, span, span, div, span, span] or alike (this one is DFS, but doesn't really matter for sake of this question).

From the three methods below which is the fastest:

  • querySelectorAll
  • NodeIterator
  • TreeWalker
like image 263
GullerYA Avatar asked May 18 '26 14:05

GullerYA


1 Answers

I've came to try another few just recently. Below the results from slowest to fastest, while specifying how the one slower than the fastest.

Chrome based results. Safari shows roughly the same numbers. Firefox has issues with that perf app and was not verified.

Method 1 (unshift) ~81% slower

const list = Array.from(root.querySelectorAll('*'));
list.unshift(root);

Method 2 (spread) ~77% slower

const list = [root, ...root.querySelectorAll('*')];

Method 3 (NodeIterator) ~32% slower

const list = [];
const ni = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT);
let next;
while (next = ni.nextNode()) {
    list.push(next);
}

Method 4 (TreeWalker) fastest

const list = [root];
const tw = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
let next;
while (next = tw.nextNode()) {
    list.push(next);
}

Bonus (empty root check) ~1% slower (~98% faster for empty root)

const list = [root];
if (root.childElementCount) {
    const tw = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
    let next;
    while (next = tw.nextNode()) {
        list.push(next);
    }
}

Observation and conclusions

  • array operations, if/when considered, show that spread (...) operator way is faster than unshift method
  • main performance gain comes from using the native iterators, TreeWalker being the fastest by far
  • it is almost always reasonable to implement that special speed-up bonus, for nested structures, the impact is neglectable but for an empty tree it runs twice faster

Bench tests can be found here.

like image 104
GullerYA Avatar answered May 20 '26 04:05

GullerYA



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!