среда, 12 октября 2011 г.

[Из песочницы] Методы querySelectorAll и querySelector. Так ли они быстры на самом деле?


В современных браузерах реализованы родные методы querySelectorAll и querySelector, которые позволяют простой отбор элементов в DOM в одну строчку используя синтаксис CSS, при этом без подключения jQuery. Во многих статьях в интернете я читал, что этот метод очень оптимизирован и делает очень быстрый перебор элементов. На сколько это правда, решил проверить проведя тесты.



Итак, заверстываем небольшую страницу:



<!DOCTYPE html>
<html>
<head>
 <title>Тест производительности javascript</title>
 <meta charset="utf-8">
</head>
<body>
 <div class="block"></div>
 <div class="block"></div>
 <div class="block"></div>
 <div class="block"></div>
 <div class="block"></div>

 <div id="a1">
  <input type="radio">
  <input type="radio">
  <input type="radio">
  <input type="radio">
  <input type="radio">
 </div>

 <div id="a2">
  <input type="checkbox">
  <input type="checkbox">
  <input type="checkbox">
  <input type="checkbox">
  <input type="checkbox">
 </div>

 <div id="a3">
  <input type="text">
  <input type="text">
  <input type="text">
  <input type="text">
  <input type="text">
 </div>
</body>
</html>


В верстке у нас 8 DIVов(5 из них с классом) и 15 инпутов(по 5 текстовых, радио и чекбоксов).

Тестироварь производительность работы разных методов будем через цикл, путем замерения времени в начале и в конце цикла. Цикл выполнит операцию сто тысяч раз.

var start = new Date()
for (var i=0;i<100000;i++){
 //тестируемый код
}
var end = new Date()
var speed = end.getTime()-start.getTime()


Конфигурация системы:

  • ОС: Windows 7 x32

  • Память: 1Гб

  • Процессор: Dual-Core e5400 2.7Ггц


Тестирование проходит в браузерах:

  • Firefox 7.01

  • Opera 11.51

  • Internet Explorer 9

  • Google Chrome 14


Для более точного тестирования, все тесты провел 10 раз и в результатах показываю среднее значение. Результаты показаны в милисекундах. Естественно, чем меньше число, тем лучше.



Начнем с простого и очень популярного примера, поиска элемента по id:

var el = document.getElementById("a1")


Результат:

  • Firefox 16

  • Opera 45

  • Internet Explorer 76

  • Google Chrome 21


А теперь попробуем тоже самое, но через querySelector

var el = document.querySelector("#a1")


Результат:

  • Firefox 166

  • Opera 282

  • Internet Explorer 295

  • Google Chrome 327


Как видно из результатов, он оказался медленнее примерно в 10 раз в Firefox, в 5 Opera, в 4 в IE9 и где-то в 15 раз в Хроме.



Теперь найдем все инпуты на странице.

var el = document.getElementsByTagName("input")

  • Firefox 21

  • Opera 82

  • Internet Explorer 122

  • Google Chrome 29


Теперь через querySelectorAll.

var el = document.querySelectorAll("input")

  • Firefox 475

  • Opera 40

  • Internet Explorer 570

  • Google Chrome 732


В Опере он оказался в 2 раза быстрее, а в остальных браузерах гораздо медленее.



Ищем элементы по классу:

var el = document.getElementsByClassName("block")

  • Firefox 29

  • Opera 83

  • Internet Explorer 119

  • Google Chrome 25


Тоже самое через querySelectorAll.

var el = document.querySelectorAll(".block")

  • Firefox 421

  • Opera 40

  • Internet Explorer 574

  • Google Chrome 750


Результаты как и в предыдущем примере. Опера с querySelectorAll работает быстрее в два раза, чем через getElementsByClassName. Другие браузеры наоборот медленее, причем с нехилой разницей.



Теперь найдем все инпуты внутри контейнера с id=«a3»

var el = document.getElementById("a3").getElementsByTagName("input")

  • Firefox 42

  • Opera 110

  • Internet Explorer 200

  • Google Chrome 43


А теперь так:

var el = document.querySelectorAll("#a3 input")

  • Firefox 630

  • Opera 41

  • Internet Explorer 633

  • Google Chrome 985


Хром показал самые плохие результаты, как и в предыдущем тесте, чему я кстати был сильно удивлен. В Опере через селекторы опять работают быстрее.



Теперь попробуем более сложную задачу. Найдем все радио и чекбокс инпуты. Сначала мы находим все инпуты, затем через цикл проверяем их type и если совпадает, то кладем элемент в массив.

var radio_checkbox = []
for(var j=0, inputs = document.getElementsByTagName("input"), len = inputs.length;j<len;j++){
 var type = inputs[j].type
 if(type=="radio" || type=="checkbox"){
 radio_checkbox.push(inputs[j])
 }
}

  • Firefox 1027

  • Opera 1122

  • Internet Explorer 2012

  • Google Chrome 829


Теперь тот же результат одной строчкой.

var el = document.querySelectorAll("input[type='radio'],input[type='checkbox']")

  • Firefox 1053

  • Opera 42

  • Internet Explorer 3025

  • Google Chrome 1414


В Firefox скорость можно считать одинаковой. В IE и Chrome через querySelectorAll оказалось медленее примерно в 1.5 раза. А Опера показала невероятно быстрый результат по сравнению с циклом, в 20 с лишним раза быстрее.



Поиск элементов используя querySelectorAll действительно очень удобный и позволяет сильно упростить код. Надеюсь, что производители браузеров оптимизируют в будущем эти методы. Тем более, даже IE8 неплохо поддерживает этот метод(только в рамках CSS2). А пока только Opera демонстрирует быстроту этого метода по сравнению с getElement(s).



UPD: по рекомендации barmaley_exe решил вывести здесь ссылки на альтернативный тест онлайн:


  • Поиск по id тест

  • Поиск по имени тега тест

  • Поиск по классу тест

  • Поиск инпутов внутри определенного контейнера тест

  • Поиск радио и чекбоксов тест. Замечу, что вариант через онлайн сервис показал другую разницу в скорости, нежели просто проверкой в браузере, которая используется в статье.





Источник: Хабрахабр - JavaScript
Оригинальная страница: [Из песочницы] Методы querySelectorAll и querySelector. Так ли они быстры на самом деле?

Комментариев нет:

Отправить комментарий