New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 12 users

Issue metadata

Status: Available
Owner: ----
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 2
Type: Bug

Sign in to add a comment

Using :scope in querySelector() takes ~2x longer than without a context element

Project Member Reported by, Mar 19 2013

Issue description

:scope was added to qS/qSA in
Running a few tests, I'm seeing using :scope takes ~2x longer.

For example:
var scope = document.querySelector('#scope');

always beats:
scope.querySelectorAll(':scope span');

My test is here:

I would expect the latter to be as fast (if not faster) since there's a context element to restrict the search. Any insight?


Comment 1 by, Mar 26 2013

I looked at and investigated this issue. So, 

var nodes = scope.querySelectorAll('span');
var nodes = scope.querySelectorAll(':scope span');

I think, querySelectorAll's cost depends on how many elements are checked to match a given selector. The first querySelectorAll has only one selector but the second one has two selectors.

Since the first and second use the same "scope" element, both querySelectoAll check the same elements. For each element,
(a) the first querySelectorAll: checks whether a given element is span or not.
(b) the second querySelectorAll: does above. Next walks up toward document root with checking whether a scoping node is in a chain from the element to root.

(b) needs to see at least one more element comparing with (a). This causes "~2x longer".

Roughly speaking, querySelector(All) needs "number of a given element's children" x "number of elements to walk up" (in this case, almost the same as number of selectors).

Project Member

Comment 2 by, Apr 5 2013

Labels: Cr-Blink
Project Member

Comment 3 by, Apr 6 2013

Labels: -Cr-Content-DOM Cr-Blink-DOM

Comment 4 by, Apr 18 2013


Comment 5 by Deleted ...@, May 22 2013

The expression could be broken in half. First evaluate the :scope portion of the expression and then evaluate the selector portion just as before as if the scope portion doesn't exist (with the caveat that you don't let parent checks pass :scope).

It should give you the desired performance gain... but since this is my first time looking at this codebase I don't think I'll be doing it, there is just too much for me to take in.
Perhaps .find won't have this issue.

Comment 7 by, Jun 10 2014

I'll take over the ownership of this bug, but looks like it is 1 year old
and needs validation (thus 'untriaged').

Comment 8 by, Jun 10 2014

I think, it would be better to make this issue "WontFix", because:

- currently we have some fast path for querySelector with simple id selector or simple tag selector, and

- the length of ":scope span" is 2 and the length of "span" is 1. So we need to spend 2x longer time for SelectorChecker::match.


Comment 9 by, Aug 6 2015

Labels: -Cr-Blink

Comment 10 by, Aug 28 2015

Status: Assigned

Comment 12 by, Aug 31 2015

.find(), defined in could solve the
performance issue?
any news or updates about  :scope in querySelector() ?
Do you have example pages where this slowdown is a problem? Having a trace from about:tracing, or a profile from the inspector where querySelector is causing you issues would be really great.
I personally don't have a page, but I have avoided using this feature in my apps due to it being slower than normal qS. We don't have metrics on this feature, but I doubt it sees very much usage. It's hard to find a real page to trace.
Components: -Blink>DOM Blink>CSS
Selector API might be in Blink > CSS.

Comment 17 by, Jul 12 2017

Labels: Performance

Comment 18 by, Jul 12 2017

Labels: Update-Quarterly

Comment 19 by, Oct 17 2017

Owner: ----
bulk edit to remove owner=me where I'm not actively looking at.

Comment 20 by, Oct 17 2017

Status: Available (was: Assigned)
mark it available.
Labels: HardBug
This can be fixed by doing what I've outlined here:

Labels: -Update-Quarterly

Sign in to add a comment