比较$(“#foo .bar”)和$(“。bar”,“#foo”)的性能

时间:2021-12-19 22:29:01

Scroll down for the getById.getByClassName vs. qSA comparison!


If we wanted to select all elements of class "bar" which are inside the element with the ID "foo", we could write this:

如果我们想要选择ID为“foo”的元素内部的“bar”类的所有元素,我们可以这样写:

$( '#foo .bar' )

or this:

或这个:

$( '.bar', '#foo' )

There are of course other methods to achieve this, but for the sake of this question, let's compare only these two methods.

当然还有其他方法可以实现这一点,但是为了这个问题,我们只比较这两种方法。

So, which of the above methods performs better? (Which needs less time to execute?)

那么,上述哪种方法表现更好? (这需要更少的时间来执行?)

I have written this performance test:

我写了这个性能测试:

(function() {
    var i;

    console.time('test1');
    for( i = 0; i < 100; i++ ) {
        $('#question-mini-list .tags');
    }
    console.timeEnd('test1');

    console.time('test2');
    for( i = 0; i < 100; i++ ) {
        $('.tags', '#question-mini-list');
    }
    console.timeEnd('test2');
})();

You have to execute it from within the console on the Stack Overflow start-page. My results are:

您必须在Stack Overflow开始页面的控制台中执行它。我的结果是:

Firefox:
test1: ~90ms
test2: ~18ms

Firefox:test1:~90ms test2:~18ms

Chrome:
test1: ~65ms
test2: ~30ms

Chrome:test1:~65ms test2:~30ms

Opera:
test1: ~50ms
test2: ~100ms

Opera:test1:~50ms test2:~100ms

So in Firefox and Chrome, the second method is multiple times faster - just as I expected. However, in Opera the situation is reversed. I wonder what's going on here.

所以在Firefox和Chrome中,第二种方法的速度要快很多倍 - 就像我预期的那样。然而,在Opera中,情况正好相反。我想知道这里发生了什么。

Could you please run the test on your machine and explain why Opera performs differently?

你可以在你的机器上运行测试并解释为什么Opera的表现不同吗?


Update

I've written this test, in order to investigate whether Opera's qSA really is super-fast. As it turns out, it is.

我已经写了这个测试,以便调查Opera的qSA是否真的超级快。事实证明,它是。

(function() {
    var i, limit = 5000, test1 = 'test1', test2 = 'test2';

    console.time( test1 );
    for( i = 0; i < limit; i += 1 ) {
        document.getElementById( 'question-mini-list' ).getElementsByClassName( 'tags' );
    }
    console.timeEnd( test1 );

    console.time( test2 );
    for( i = 0; i < limit; i += 1 ) {
        document.querySelectorAll( '#question-mini-list .tags' );
    }
    console.timeEnd( test2 );
})();

Again, you have to run this code from within the console on the Stack Overflow start-page. I used the Firebug Lite bookmarklet for IE9 (since that browser doesn't implement console.time).

同样,您必须在Stack Overflow开始页面的控制台中运行此代码。我使用了针对IE9的Firebug Lite书签(因为该浏览器没有实现console.time)。

So, I compared this method:

所以,我比较了这个方法:

document.getelementById( 'A' ).getElementsByClassName( 'B' );

to this method:

这个方法:

document.querySelectorAll( '#A .B' );

I've executed the above script five consecutive times in each browser. The arithmetic means are:

我在每个浏览器中连续五次执行上面的脚本。算术手段是:

比较$(“#foo .bar”)和$(“。bar”,“#foo”)的性能

(All numbers are in milliseconds.)

(所有数字均以毫秒为单位。)

So, the performance of the first method is pretty much the same in the tested browsers (16-36ms). However, while qSA is much slower compared to the first method, in Opera it actually is faster!

因此,第一种方法的性能在测试的浏览器中几乎相同(16-36ms)。然而,虽然qSA比第一种方法慢得多,但在Opera中它实际上更快!

So, qSA optimization is possible, I wonder what the other browsers are waiting for...

所以,qSA优化是可能的,我想知道其他浏览器在等什么...

3 个解决方案

#1


3  

jQuery/Sizzle will avoid using the JavaScript based Sizzle engine if the browser supports querySelectorAll, and if you pass a valid selector (no custom, non-CSS selectors).

如果浏览器支持querySelectorAll,并且传递了一个有效的选择器(没有自定义的非CSS选择器),jQuery / Sizzle将避免使用基于JavaScript的Sizzle引擎。

This means that you're ultimately comparing implementations of querySelectorAll, assuming you're testing browsers that support it.

这意味着您最终要比较querySelectorAll的实现,假设您正在测试支持它的浏览器。

There are other optimizations that jQuery or Sizzle uses, so it's tricky when comparing different types of DOM selection in different browsers.

还有jQuery或Sizzle使用的其他优化,因此在不同浏览器中比较不同类型的DOM选择时,这很棘手。

The reason for Opera's performance result seems to be that they have a very highly optimized querySelectorAll implementation. qSA, being a relatively new method, hasn't been quite as optimized in some browsers compared to older methods like getElementsByTagName.

Opera的性能结果的原因似乎是他们有一个非常高度优化的querySelectorAll实现。与较旧的方法(如getElementsByTagName)相比,qSA是一种相对较新的方法,在某些浏览器中并没有得到优化。

#2


1  

And the winner is....

最终获胜者是....

test 3 $('#question-mini-list').find('.tags');

test 3 $('#question-mini-list')。find('。tags');

  • test1: 25ms
  • test1:25ms
  • test2: 19ms
  • test2:19ms
  • test3: 10ms
  • test3:10ms

The two methods you suggested are not equivalent.

您建议的两种方法不相同。

test 1: Sizzle parses from right to left (don't ask it to search ever element on the page, then restrict to an ID).

测试1:Sizzle从右到左解析(不要求它在页面上搜索任何元素,然后限制为ID)。

test 2: Using a string as a context is generally of no use, use elements as a context.

测试2:使用字符串作为上下文通常没有用,使用元素作为上下文。

test 3: Finding elements with an id is blazingly fast. Once you're there it's a breeze to focus in on an item of a given class.

测试3:查找具有id的元素非常快。一旦你在那里,轻松地专注于给定类的项目。

#3


1  

For reference, this is 30x faster:

作为参考,这快30倍:

document.getElementById("foo").getElementsByClassName("bar");

See jsPerf: http://jsperf.com/jquery-selector-variations/3. This would need a shim to work in older versions of IE.

请参阅jsPerf:http://jsperf.com/jquery-selector-variations/3。这需要垫片才能在旧版IE中使用。

While jQuery is extremely useful, if speed is of the utmost, it's not always the best tool for the job.

虽然jQuery非常有用,但如果速度最高,它并不总是最好的工具。

#1


3  

jQuery/Sizzle will avoid using the JavaScript based Sizzle engine if the browser supports querySelectorAll, and if you pass a valid selector (no custom, non-CSS selectors).

如果浏览器支持querySelectorAll,并且传递了一个有效的选择器(没有自定义的非CSS选择器),jQuery / Sizzle将避免使用基于JavaScript的Sizzle引擎。

This means that you're ultimately comparing implementations of querySelectorAll, assuming you're testing browsers that support it.

这意味着您最终要比较querySelectorAll的实现,假设您正在测试支持它的浏览器。

There are other optimizations that jQuery or Sizzle uses, so it's tricky when comparing different types of DOM selection in different browsers.

还有jQuery或Sizzle使用的其他优化,因此在不同浏览器中比较不同类型的DOM选择时,这很棘手。

The reason for Opera's performance result seems to be that they have a very highly optimized querySelectorAll implementation. qSA, being a relatively new method, hasn't been quite as optimized in some browsers compared to older methods like getElementsByTagName.

Opera的性能结果的原因似乎是他们有一个非常高度优化的querySelectorAll实现。与较旧的方法(如getElementsByTagName)相比,qSA是一种相对较新的方法,在某些浏览器中并没有得到优化。

#2


1  

And the winner is....

最终获胜者是....

test 3 $('#question-mini-list').find('.tags');

test 3 $('#question-mini-list')。find('。tags');

  • test1: 25ms
  • test1:25ms
  • test2: 19ms
  • test2:19ms
  • test3: 10ms
  • test3:10ms

The two methods you suggested are not equivalent.

您建议的两种方法不相同。

test 1: Sizzle parses from right to left (don't ask it to search ever element on the page, then restrict to an ID).

测试1:Sizzle从右到左解析(不要求它在页面上搜索任何元素,然后限制为ID)。

test 2: Using a string as a context is generally of no use, use elements as a context.

测试2:使用字符串作为上下文通常没有用,使用元素作为上下文。

test 3: Finding elements with an id is blazingly fast. Once you're there it's a breeze to focus in on an item of a given class.

测试3:查找具有id的元素非常快。一旦你在那里,轻松地专注于给定类的项目。

#3


1  

For reference, this is 30x faster:

作为参考,这快30倍:

document.getElementById("foo").getElementsByClassName("bar");

See jsPerf: http://jsperf.com/jquery-selector-variations/3. This would need a shim to work in older versions of IE.

请参阅jsPerf:http://jsperf.com/jquery-selector-variations/3。这需要垫片才能在旧版IE中使用。

While jQuery is extremely useful, if speed is of the utmost, it's not always the best tool for the job.

虽然jQuery非常有用,但如果速度最高,它并不总是最好的工具。