Сравнение производительности $ ("# foo .bar") и $ (". Bar", "#foo") - PullRequest
9 голосов
/ 22 декабря 2011

Прокрутите вниз для сравнения getById.getByClassName с qSA!


Если мы хотим выбрать все элементы класса "bar", которые находятся внутри элемента с идентификатором "foo", мы могли бы написать это:

$( '#foo .bar' )

или это:

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

Конечно, есть и другие способы для достижения этой цели, но ради этого вопроса давайте сравним только эти два метода.

Итак, какой из вышеперечисленных методов работает лучше? (Что требует меньше времени для выполнения?)

Я написал этот тест производительности:

(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');
})();

Вы должны выполнить его из консоли на стартовой странице Переполнение стека . Мои результаты:

Firefox:
test1: ~ 90 мс
test2: ~ 18 мс

Chrome:
test1: ~ 65 мс
test2: ~ 30 мс

Opera:
test1: ~ 50 мс
test2: ~ 100 мс

Так что в Firefox и Chrome второй метод работает в несколько раз быстрее - как я и ожидал. Однако в Опере ситуация обратная. Интересно, что здесь происходит?

Не могли бы вы запустить тест на своем компьютере и объяснить, почему Opera работает по-другому?


Обновление

Я написал этот тест, чтобы выяснить, действительно ли qSA от Opera действительно супербыстрый. Оказывается, это так.

(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 );
})();

Опять же, вы должны запустить этот код из консоли на стартовой странице переполнения стека. Я использовал букмарклет Firebug Lite для IE9 (поскольку этот браузер не поддерживает console.time).

Итак, я сравнил этот метод:

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

к этому методу:

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

Я выполнил вышеописанный скрипт пять раз подряд в каждом браузере. Арифметические средства:

enter image description here

(все числа в миллисекундах.)

Итак, производительность первого метода почти одинакова в протестированных браузерах (16-36 мс). Однако, хотя qSA намного медленнее по сравнению с первым методом, в Opera он на самом деле быстрее!

Итак, оптимизация qSA возможна, интересно, чего ждут другие браузеры ...

Ответы [ 3 ]

3 голосов
/ 22 декабря 2011

jQuery / Sizzle избегает использования движка Sizzle на основе JavaScript, если браузер поддерживает querySelectorAll и если вы передаете допустимый селектор (без пользовательских селекторов, кроме CSS).

Это означает, что вы в конечном итоге сравниваете реализации querySelectorAll, предполагая, что вы тестируете браузеры, которые его поддерживают.

Существуют и другие оптимизации, которые использует jQuery или Sizzle, поэтому сложно сравнивать разные типы выбора DOM в разных браузерах.

Похоже, что результат производительности Opera заключается в очень оптимизированной реализации querySelectorAll. qSA, будучи относительно новым методом, не был так оптимизирован в некоторых браузерах по сравнению со старыми методами, такими как getElementsByTagName.

1 голос
/ 22 декабря 2011

Для справки, это в 30 раз быстрее:

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

См. JsPerf: http://jsperf.com/jquery-selector-variations/3. Для работы с более ранними версиями IE потребуется прокладка.

Хотя jQuery чрезвычайно полезен, если скорость максимальна, он не всегда лучший инструмент для работы.

1 голос
/ 22 декабря 2011

И победитель ....

тест 3 $('#question-mini-list').find('.tags');

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

Два предложенных вами метода не эквивалентны.

тест 1 : Sizzle анализирует справа налево (не просите его искать когда-либо элемент на странице, а затем ограничиваться идентификатором).

test 2 : Использование строки в качестве контекста, как правило, бесполезно, используйте элементы в качестве контекста.

тест 3 : Поиск элементов с идентификатором происходит невероятно быстро. Как только вы окажетесь там, легко сосредоточиться на предмете данного класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...