Skip to content

Instantly share code, notes, and snippets.

@denilsonsa
Last active September 10, 2021 12:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save denilsonsa/6fdcc5a726220a85eb7c6a00e955d532 to your computer and use it in GitHub Desktop.
Save denilsonsa/6fdcc5a726220a85eb7c6a00e955d532 to your computer and use it in GitHub Desktop.
getElementsByClassName vs getElementById vs querySelector (http://jsbench.github.io/#6fdcc5a726220a85eb7c6a00e955d532) #jsbench #jsperf
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>getElementsByClassName vs getElementById vs querySelector</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script>
<script src="./suite.js"></script>
</head>
<body>
<h1>Open the console to view the results</h1>
<h2><code>cmd + alt + j</code> or <code>ctrl + alt + j</code></h2>
</body>
</html>
"use strict";
(function (factory) {
if (typeof Benchmark !== "undefined") {
factory(Benchmark);
} else {
factory(require("benchmark"));
}
})(function (Benchmark) {
var suite = new Benchmark.Suite;
Benchmark.prototype.setup = function () {
window.generated_divs = 5000;
let root = document.createElement("div");
for(let i = 0; i < generated_divs; i++) {
let el = document.createElement("div");
el.id = `foo${i}`;
el.className = `foo${i}`;
el.setAttribute(`foo${i}`, '');
root.appendChild(el);
}
document.body.appendChild(root);
};
Benchmark.prototype.teardown = function () {
document.body.removeChild(root);
root = null;
};
suite.add("getElementById", function () {
// getElementById
let i = Math.floor(Math.random() * window.generated_divs);
let element = document.getElementById(`foo${i}`);
});
suite.add("getElementsByClassName", function () {
// getElementsByClassName
let i = Math.floor(Math.random() * window.generated_divs);
let element = document.getElementsByClassName(`foo${i}`);
});
suite.add("querySelector('#id')", function () {
// querySelector('#id')
let i = Math.floor(Math.random() * window.generated_divs);
let element = document.querySelector(`#foo${i}`);
});
suite.add("querySelector('.class')", function () {
// querySelector('.class')
let i = Math.floor(Math.random() * window.generated_divs);
let element = document.querySelector(`.foo${i}`);
});
suite.add("querySelector('[attr]]')", function () {
// querySelector('[attr]]')
let i = Math.floor(Math.random() * window.generated_divs);
let element = document.querySelector(`[foo${i}]`);
});
suite.on("cycle", function (evt) {
console.log(" - " + evt.target);
});
suite.on("complete", function (evt) {
console.log(new Array(30).join("-"));
var results = evt.currentTarget.sort(function (a, b) {
return b.hz - a.hz;
});
results.forEach(function (item) {
console.log((idx + 1) + ". " + item);
});
});
console.log("getElementsByClassName vs getElementById vs querySelector");
console.log(new Array(30).join("-"));
suite.run();
});
@sschmidTU
Copy link

sschmidTU commented Sep 8, 2021

The benchmark for getElementsByClassName was actually incorrect, because the method only returns a HTMLCollection, essentially a query term. You need to evaluate it before it finds elements.
So evaluating the result with [0] shows the true performance:
image
image
full screenshot of upper part:
https://user-images.githubusercontent.com/33069673/132558324-14831ed0-12bc-43e3-96bf-c140a339fa7a.png

Here's my fork of the benchmark with the above fix:
http://jsbench.github.io/#a8f9a872efc2063a9365976fc26946e2

For that reason, in your version on jsbench getElementsByClassName outperforms getElementsById, which makes no sense, since the ids are indexed (in a hashmap = O(1)), while getElementsByClassName needs to search the DOM tree.
https://user-images.githubusercontent.com/33069673/132554466-129ca976-48d2-4d63-9ffe-e1c446170b01.png

@denilsonsa otherwise great benchmark, thanks for sharing it (=

@denilsonsa
Copy link
Author

Great finding, @sschmidTU! Fully agree with your commments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment