getelementbyid-vs-queryselector-vs-children-vs-tags

Benchmark created by Eric on


Description

Compare different methods of selecting. For a long while, it seems that using document.getElementById is always faster - even if you try to get 13 elements.

I have also ran these tests with nearly 700 lines of HTML. On Chrome16 the first test resulted in 550k executions, second had 750k executions! On iPad1 the first test had 32k executions, second test had 22k executions.

I.e. a contrasting result for both targets..

Appearently document.getElementById works faster for about all cases. I did not encounter any situation (for iPad!) that document.getElementById was NOT faster.

In this testcase I added some clutterHTML from jsperf.com to slow the repeating (13x) document.getElementById down.

Preparation HTML

<article>
  <h1>
    <strong>
      <em title="JavaScript">
        THIS IS SAMPLE OUTPUT
      </em><br/>
      <em title="JavaScript">
        THIS IS SAMPLE OUTPUT
      </em><br/>
      <em title="JavaScript">
        THIS IS SAMPLE OUTPUT
      </em><br/>
      <em title="JavaScript">
        THIS IS SAMPLE OUTPUT
      </em><br/>
      Perf
    </strong>
    — JavaScript performance playground
  </h1>
        THIS IS SAMPLE OUTPUT
  <h2>
    What is jsPerf?
  </h2>
  <p>
    jsPerf aims to provide an easy way to create and share
    <a href="/browse" title="View some examples by browsing the jsPerf test cases">test cases</a>
    , comparing the performance of different JavaScript snippets by running benchmarks.
    For more information, see
    <a href="/faq" title="Frequently asked questions">the FAQ</a>
    .
  </p>
  <h2>
    Create a test case
  </h2>
  <form action="/" method="post">
    <fieldset>
      <h33>
        Your details (optional)
      </h33>
      <div>
        <label for="author">
          Name
        </label>
        <input type="text" name="author" id="author">
      </div>
      <div>
        <label for="author-email">
          Email
        </label>
        <label class="inline">
          <input type="email" name="author-email" id="author-email">
          (won’t be displayed; might be used for Gravatar)
        </label>
      </div>
      <div>
        <label for="author-url">
          URL
        </label>
        <input type="url" name="author-url" id="author-url">
      </div>
    </fieldset>
    <fieldset>
      <h33>
        Test case details
      </h33>
      <div>
        <label for="title">
          Title
          <em title="This field is required">
            *
          </em>
        </label>
        <input type="text" name="title" id="title" required>
      </div>
      <div>
        <label for="slug">
          Slug
          <em title="This field is required">
            *
          </em>
        </label>
        <input type="text" name="slug" id="slug" pattern="[a-z0-9](?:-?[a-z0-9])*" required>
        <p class="preview">
          Test case URL will be
          <samp>
            http://jsperf.com/
            <mark>
              slug
            </mark>
          </samp>
        </p>
      </div>
      <div>
        <label for="visible">
          Published
        </label>
        <label class="inline">
          <input type="checkbox" value="y" name="visible" id="visible" checked>
          (uncheck if you want to fiddle around before making the page public)
        </label>
      </div>
      <div>
        <label for="info">
          Description
          <span>
            (in case you feel further explanation is needed)
          </span>
          <span>
            (Markdown syntax is allowed)
          </span>
        </label>
        <textarea name="info" id="info">
        </textarea>
      </div>
      <div class="question">
        <label for="question">
          Are you a spammer?
          <span>
            (just answer the question)
          </span>
        </label>
        <input type="text" name="question" id="question">
      </div>
      <fieldset>
        <h33>
          Preparation code
        </h33>
        <div>
          <label for="prep-html">
            Preparation code HTML
            <span>
              (this will be inserted in the
              <code>
                &lt;body>
              </code>
              of a valid HTML5 document in standards mode)
            </span>
            <span>
              (useful when testing DOM operations or including libraries)
            </span>
          </label>
          <textarea name="prep-html" id="prep-html">
          </textarea>
          <p id="add-libraries">
            Include JavaScript libraries as follows:
            <code>
              &lt;script src="//cdn.ext/library.js">&lt;/script>
            </code>
          </p>
        </div>
        <div>
          <label for="setup">
            Define
            <code>
              setup
            </code>
            for all tests
            <span>
              (variables, functions, arrays or other objects that will be used in the tests)
            </span>
            <span>
              (runs before each clocked test loop, outside of the timed code region)
            </span>
            <span>
              (e.g. define local test variables, reset global variables, clear
              <code>
                canvas
              </code>
              , etc.)
            </span>
            <span>
              (
              <a href="/faq#setup-teardown">see FAQ</a>
              )
            </span>
          </label>
          <textarea name="setup" id="setup">
          </textarea>
        </div>
        <div>
          <label for="teardown">
            Define
            <code>
              teardown
            </code>
            for all tests
            <span>
              (runs after each clocked test loop, outside of the timed code region)
            </span>
            <span>
              (
              <a href="/faq#setup-teardown">see FAQ</a>
              )
            </span>
          </label>
          <textarea name="teardown" id="teardown">
          </textarea>
        </div>
      </fieldset>
      <fieldset id="tests">
        <h33>
          Code snippets to compare
        </h33>
        <fieldset>
          <h4>
            Test 1
          </h4>
          <div>
            <label for="test[1][title]">
              Title
              <em title="This field is required">
                *
              </em>
            </label>
            <input type="text" name="test[1][title]" id="test[1][title]" required>
          </div>
          <div>
            <label for="test[1][defer]">
              Async
            </label>
            <label class="inline">
              <input type="checkbox" value="y" name="test[1][defer]" id="test[1][defer]">
              (check if this is an
              <a href="/faq#async">asynchronous test</a>
              )
            </label>
          </div>
          <div>
            <label for="test[1][code]">
              Code
              <em title="This field is required">
                *
              </em>
              <span>
                (No need for loops in the test code; we’ll take care of that for you)
              </span>
            </label>
            <textarea name="test[1][code]" id="test[1][code]" class="code-js" required>
            </textarea>
          </div>
        </fieldset>
        <fieldset>
          <h4>
            Test 2
          </h4>
          <div>
            <label for="test[2][title]">
              Title
              <em title="This field is required">
                *
              </em>
            </label>
            <input type="text" name="test[2][title]" id="test[2][title]" required>
          </div>
          <div>
            <label for="test[2][defer]">
              Async
            </label>
            <label class="inline">
              <input type="checkbox" value="y" name="test[2][defer]" id="test[2][defer]">
              (check if this is an
              <a href="/faq#async">asynchronous test</a>
              )
            </label>
          </div>
          <div>
            <!-- it's about this part -->
            <div id="id1">
              <div id="id2">
                <div>
                  <polygon id="id3" />
                  <polygon id="id4" />
                  <polygon id="id5" />
                </div>
              </div>
            </div>
            <label for="test[2][code]">
              Code
              <em title="This field is required">
                *
              </em>
            </label>
            <textarea name="test[2][code]" id="test[2][code]" class="code-js" required>
            </textarea>
          </div>
        </fieldset>
      </fieldset>
      <div class="buttons">
        <input type="submit" class="submit" value="Save test case" title="Save and view test case">
      </div>
    </fieldset>
  </form>
</article>
END OF SAMPLE OUTPUT<br/>
END OF SAMPLE OUTPUT<br/>
END OF SAMPLE OUTPUT<br/>
END OF SAMPLE OUTPUT<br/>
END OF SAMPLE OUTPUT<br/>

Test runner

Ready to run.

Testing in
TestOps/sec
3x document.getElementById
var id3 = document.getElementById("id3");
var id4 = document.getElementById("id4");
var id5 = document.getElementById("id5");
ready
1x ById -> 3x ByTagName [index]
var elements = document.getElementById("id2").getElementsByTagName("polygon");
var id3 = elements[0];
var id4 = elements[1];
var id5 = elements[2];
ready
1 elemById 3x querySelect
var root = document.getElementById("id2");
var id3 = root.querySelector("#id3");
var id4 = root.querySelector("#id4");
var id5 = root.querySelector("#id5");
ready
1 elemById 3x children
var root = document.getElementById("id2").children[0];
var id3 = root.children[0];
var id4 = root.children[1];
var id5 = root.children[2];
ready
3x elementsByTagName
var elements = document.getElementsByTagName("polygon");
var id3 = elements[0];
var id4 = elements[1];
var id5 = elements[2];
ready

Revisions

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