https://jsperf.com/getelementbyid-vs-id-function

JavaScript performance comparison

Test case created by mickert

Preparation code

<div id="divContainer"></div>

<script>

    console.time('* Timer test setup');

    const divContainerId = 'divContainer';

    const testSetSize = 1000;
    const divTreeWeight = [
        [
            1,
            1
        ],
        [
            3,
            [
                4,
                5,
                4
            ],
            3
        ],
        [
            1,
            1
        ]
    ];
    const sleepTimeBeforeTests = 2000;
    const sleepTimeAfterTests = 1000;


    const divIds = Array(testSetSize).fill('');
    const resultIds = Array(testSetSize).fill('');
    let runningTestCounter = 0;

    const fnArrowLightest = id_ => document.getElementById(id_);
    const fnArrowLight = (id_) => document.getElementById(id_);
    const fnArrowFat = id_ => { return document.getElementById(id_); }
    const fnArrowFatter = (id_) => { return document.getElementById(id_); }
    const fnExpression = function (id_) { return document.getElementById(id_); }
    const fnExpressionNamed = function fnExpressionName(id_) { return document.getElementById(id_); }
    function fnDeclaration(id_) { return document.getElementById(id_); }


    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    if (!Array.prototype.flat) Object.defineProperty(Array.prototype, 'flat', {
        value: function flat(depth = 1) {
            // * Array.prototype.flat polyfill using Array.prototype.reduce 
            // * (ↄ) 2019 Michel.Sijmons.net. Use freely, but note: This material is provided "as is", with absolutely no warranty expressed or implied. ANY USE IS AT YOUR OWN RISK!
            if (this === null) throw new TypeError('Array.prototype.flat ' + 'called on null or undefined');
            else {
                const flat = (arr_, depth_) => (depth_ > 0) ? arr_.reduce((_acc, _val) => _acc.concat((depth_ > 0 && Array.isArray(_val)) ? flat(_val, depth_ - 1) : _val), []) : arr_;
                return flat(this, depth);
            }
        }
    });

    ((divContainerId_, testSetSize_, divIds_, divTreeWeight_) => {

        function shuffleArray(array_) {
            const _array = array_;
            for (let i = _array.length - 1; i > 0; i--) {
                const j = ~~((window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295) * (i + 1));
                [_array[i], _array[j]] = [_array[j], _array[i]];
            }
        }

        for (let i = 0; i < testSetSize_; i++) { divIds_[i] = 'div' + window.crypto.getRandomValues(new Uint32Array(4)).reduce((a, e) => a + e.toString(36), '') + i }
        shuffleArray(divIds_);

        const _flatdivTreeWeight = divTreeWeight_.flat(Infinity);
        const _divTreeTotalBranches = _flatdivTreeWeight.length;
        const _divTreeTotalWeight = _flatdivTreeWeight.reduce((a, e) => a + e, 0);
        const _weightMultiplier = ~~(testSetSize_ / _divTreeTotalWeight);
        const _restWeight = testSetSize_ % _weightMultiplier;


        let _divContainer = document.getElementById(divContainerId_);
        if (!_divContainer) {
            _divContainer = document.createElement('div');
            _divContainer.id = divContainerId_;
            document.getElementsByTagName('body')[0].appendChild(_divContainer);
        }

        let divIdx = 0;
        let treeLevel = 0;
        let branchCount = 0;

        function getDivBranch(div_, branch_) {
            const _div = div_;
            const _branch = branch_;
            if (Array.isArray(_branch)) {
                treeLevel++;
                for (let i = 0; i < _branch.length; i++) {
                    console.log(`* creating branch #${branchCount} at level ${treeLevel}.`);
                    const _branchDiv = document.createElement('div');
                    _branchDiv.classList = `branch branch${branchCount} treeLevel${treeLevel}`;
                    _branchDiv.appendChild(getDivBranch(document.createDocumentFragment(), _branch[i]));
                    _div.appendChild(_branchDiv);
                }
                treeLevel--;
            } else {
                const _setSize = (++branchCount !== _divTreeTotalBranches)
                    ? _branch * _weightMultiplier
                    : (_branch * _weightMultiplier) + _restWeight
                    ;
                console.log(`* filling branch #${branchCount} at level ${treeLevel} with ${_setSize} divs.`);
                for (let i = 0; i < _setSize; i++) {
                    const _leafDiv = document.createElement('div');
                    _leafDiv.id = divIds_[divIdx++];
                    _leafDiv.classList = classList = `leaf branch${branchCount} treeLevel${treeLevel}`;
                    _div.appendChild(_leafDiv);
                }
            }
            return _div;
        }

        _divContainer.appendChild(getDivBranch(document.createDocumentFragment(), divTreeWeight_));

        console.log(`* created ${branchCount} branches with a total of ${divIdx} divs.`);

        console.log('_divContainer:', _divContainer);
        console.dir(_divContainer);

        shuffleArray(divIds_);
    })(divContainerId, testSetSize, divIds, divTreeWeight);

    console.timeEnd('* Timer test setup');

    (async (sleepTime_) => {
        console.log(`* Clearing result array and sleeping for ${sleepTimeBeforeTests / 1000} seconds before test.`);
        resultIds.fill('');
        await sleep(sleepTime_);
        console.log('* Continuing... ');
    })(sleepTimeBeforeTests);

</script>
      
<script>
Benchmark.prototype.setup = function() {
  // setup
  if (runningTestCounter++ === 0 && console.timeLog) console.time('* Tests total running time');
  if (console.timeLog) console.timeLog('* Tests total running time');
  console.time(`* Test ${runningTestCounter} running time`);
  

};

Benchmark.prototype.teardown = function() {
  // teardown
  console.timeEnd(`* Test ${runningTestCounter} running time`);
  console.log('* Clearing result array');
  if (console.timeLog) console.timeLog('* Tests total running time');
  resultIds.fill('');
  console.log('* Continuing with next test.');
  

};
</script>

Preparation code output

<div id="divContainer"></div>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
inline getElementById
for (let i = 0; i < testSetSize; i++) { resultIds[i] = document.getElementById(divIds[i]); }
pending…
fnArrowLightest
for (let i = 0; i < testSetSize; i++) { resultIds[i] = fnArrowLightest(divIds[i]); }
pending…
fnArrowLight
for (let i = 0; i < testSetSize; i++) { resultIds[i] = fnArrowLight(divIds[i]); }
pending…
fnArrowFat
for (let i = 0; i < testSetSize; i++) { resultIds[i] = fnArrowFat(divIds[i]); }
pending…
fnArrowFatter
for (let i = 0; i < testSetSize; i++) { resultIds[i] = fnArrowFatter(divIds[i]); }
pending…
fnExpression
for (let i = 0; i < testSetSize; i++) { resultIds[i] = fnExpression(divIds[i]); }
pending…
fnExpressionNamed
for (let i = 0; i < testSetSize; i++) { resultIds[i] = fnExpressionNamed(divIds[i]); }
pending…
fnDeclaration
for (let i = 0; i < testSetSize; i++) { resultIds[i] = fnDeclaration(divIds[i]); }
pending…
inline getElementById (2)
for (let i = 0; i < testSetSize; i++) { resultIds[i] = document.getElementById(divIds[i]); }
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

Compare results of other browsers

0 Comments