Closed
Bug 1427926
Opened 6 years ago
Closed 6 years ago
getElementsByAttribute("attribute", "*") much faster than querySelectorAll("[attribute]")
Categories
(Core :: DOM: Core & HTML, enhancement, P3)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
INVALID
People
(Reporter: myk, Unassigned)
References
(Blocks 1 open bug)
Details
Attachments
(1 file)
776 bytes,
text/html
|
Details |
This microbenchmark I wrote for about:preferences shows that document.getElementsByAttribute("attribute", "*") is much faster (~25x) than document.querySelectorAll("[attribute]"): performance.mark("getElementsByAttribute-start"); for (let i = 0; i < 1000; i++) { const elements = document.getElementsByAttribute("preference", "*"); } performance.mark("getElementsByAttribute-end"); performance.measure("getElementsByAttribute", "getElementsByAttribute-start", "getElementsByAttribute-end"); performance.mark("querySelectorAll-start"); for (let i = 0; i < 1000; i++) { const elements = document.querySelectorAll("[preference]"); } performance.mark("querySelectorAll-end"); performance.measure("querySelectorAll", "querySelectorAll-start", "querySelectorAll-end"); performance.getEntries().forEach(e => console.log(JSON.stringify(e))); Fluent uses document.querySelectorAll("[attribute]") extensively, and interfaces like about:preferences will eventually need to use it in order to migrate to HTML, so it might be helpful to optimize it for this (common?) case, or provide an HTML equivalent for document.getElementsByAttribute("preference", "*").
Comment 1•6 years ago
|
||
This is not very surprising. querySelector* is by design, I'd say, slower than getElement(s)By*. It after all needs to parse and run the selector and *By* methods just need to check whether the value is '*' or something else and traverse the DOM, or in getElementById case just do a hashtable lookup. Also, getElementsByAttribute just returns a NodeList which hasn't yet searched anything. The test would be a tad more reasonable if one did something like document.getElementsByAttribute("preference", "*").length; and document.querySelectorAll("[preference]").length; The nice thing with querySelectorAll is that it returns non-live NodeList. A testcase attached to this bug would be nice for profiling, as always.
Comment 2•6 years ago
|
||
Comment 3•6 years ago
|
||
Hmm, that might not be realistic enough testcase.
Comment 4•6 years ago
|
||
myk, could you test with .length; since right now the test in the initial comment is sort of comparing apples and oranges.
Flags: needinfo?(myk)
Reporter | ||
Comment 5•6 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #1) > This is not very surprising. querySelector* is by design, I'd say, slower > than getElement(s)By*. It after all needs to parse and run the selector and > *By* methods just need to check whether the value is '*' or something else > and traverse the DOM, or in getElementById case just do a hashtable lookup. > Also, getElementsByAttribute just returns a NodeList which hasn't yet > searched anything. > The test would be a tad more reasonable if one did something like > document.getElementsByAttribute("preference", "*").length; > and > document.querySelectorAll("[preference]").length; > > The nice thing with querySelectorAll is that it returns non-live NodeList. > > A testcase attached to this bug would be nice for profiling, as always. I could attach a testcase for profiling, but it'd be hard to run, since getElementsByAttribute only works in XUL, and Firefox no longer loads remote XUL (not even if the "remote" XUL is a local file). However, an easy way to run the testcase in comment #0 is to load about:preferences in a tab, open the Web Console, and evaluate the testcase code in the console. (In reply to Olli Pettay [:smaug] from comment #4) > myk, could you test with .length; > since right now the test in the initial comment is sort of comparing apples > and oranges. Indeed, testing with .length as in the following testcase results in querySelectorAll becoming a few milliseconds *faster* (at ~35ms) than getElementsByAttribute (at ~38ms) on my machine: performance.mark("getElementsByAttribute-start"); for (let i = 0; i < 1000; i++) { const elements = document.getElementsByAttribute("preference", "*").length; } performance.mark("getElementsByAttribute-end"); performance.measure("getElementsByAttribute", "getElementsByAttribute-start", "getElementsByAttribute-end"); performance.mark("querySelectorAll-start"); for (let i = 0; i < 1000; i++) { const elements = document.querySelectorAll("[preference]").length; } performance.mark("querySelectorAll-end"); performance.measure("querySelectorAll", "querySelectorAll-start", "querySelectorAll-end"); performance.getEntries().forEach(e => console.log(JSON.stringify(e))); So perhaps this is actually a non-issue.
Flags: needinfo?(myk)
Updated•6 years ago
|
Priority: -- → P3
Reporter | ||
Comment 6•6 years ago
|
||
Upon further consideration, I think we should close this as a non-issue. If we identify a specific impact in the future, then we can reopen (or, more likely, file a new bug).
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → INVALID
Assignee | ||
Updated•5 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•