Сравнение скорости выполнения функций в JavaScript
Что круче: числа или строки?
Часто возникает желание узнать, что же все-таки круче: «A» или «B». Например, сегодня я задумался — насколько медленнее работает поиск по подстроке против чисел. Да-да, именно так «насколько медленнее…». Задача — реализация прав доступа.
Экспозиция
-
Unix Way: права задаются в виде восьмеричного числа, которое конвертируется в двоичное, и каждый разряд этого числа отвечает за определенный тип прав. Например 5 в восмеричной — это 101 в двоичной. И теперь по порядку: 1 — администрирование, 0 — нет редактирования, 1 — чтение.
-
Строки: права задаются в виде строки которая состоит из букв «rwa», где «r» — чтение, «w» — редактирование, «a» — администрирование.
Для меня было очевидно, что поиск по подстроке должен быть медленнее, чем «простая математика». Но мне было интересно, на сколько медленнее. Я ждал каких-то космических значений, ибо гениальное unix-way решение выглядело очень по-гиковски. Мне казалось, что разница должна была быть в раза в три.
Как узнать, что же круче?!
В Dash у меня хранится специальный скрипт. Я нашел его в дебрях комментариев хабра, и теперь всегда использую для того, чтобы проверить, какое из решений быстрее. Я нахожу это занятие очень забавным.
/**
* from: habrahabr.ru/ somewhere in comments
* Полезная штука для того, чтобы оценить какой оператор или конструкция быстрее.
*/
function count(f, q){
console.profile()
while(q--){
f();
}
console.profileEnd()
}
function f1( x ){
return typeof x == 'undefined';
}
function f2( x ){
return typeof x === 'undefined';
}
count(f1, 10000000000);
count(f2, 10000000000);
Нууу!!1 Что круче??!!111один
В результате, пытаясь минимально сгладить различия между двумя реализациями, у меня получился следующий код.
function count(f, q){
console.profile()
while(q--){
f();
}
console.profileEnd()
}
function f1( x ){
var data = [7, 5, 1];
for (var i = 0; i < data.length; i++) {
var r = data[i];
r[0]==1 ? 'read' : false;
r[1]==1 ? 'write' : false;
r[2]==1 ? 'admin' : false;
}
}
function f2( x ){
var data = ['r', 'rw', 'rwa'];
for (var i = 0; i < data.length; i++) {
var r = data[i];
!! ~r.indexOf('r') ? 'read' : false;
!! ~r.indexOf('w') ? 'write' : false;
!! ~r.indexOf('a') ? 'admin' : false;
}
}
count(f1, 10000000);
count(f2, 10000000);
Отвечай!!!!1
Неожиданно, все вышло совсем не так. Числа знатно прососали буквам. Мир никогда не будет прежним. Смотрите сами:
- Unix Way: 5962ms
- Строки: 4989ms
Мораль
Все эти псевдоинтеллектуальные исследования в одном браузере вряд ли имеют какой-то смысл, но делать «зарубки на лавках» как видишь, очень весело! Советую, взять на вооружение этот удобный сниппет для, так сказать, a/b тестирования.
На самом деле нет
По правде сказать, я допустил ошибку в функции получения прав из числа. И вообще, написал ее очень коряво. Правильный вариант такой:
function f1( x ){
var data = [7, 5, 1];
for (var i = 0; i < data.length; i++) {
var r = data[i];
r & 1 ? 'read' : false;
r & 2 ? 'write' : false;
r & 4 ? 'admin' : false;
}
}
И тогда-то числа и начнут знатно нагибать строки. Примерно раз в 20.
Это вернуло мне веру в мир.
Похожие статьи:
-
Анализ покрытия JavaScript-кода тестами
Вместе с нашими друзьями: Mocha, JSCoverage, Coveralls и Travis
-
Паттерн «объект-представление»
7 паттернов для рефакторинга JavaScript-приложений
-
Паттерн «объект-запрос»
7 паттернов для рефакторинга JavaScript-приложений
-
ASI и мистические знаки перед IIFE в JavaScript
Сжигаем ведьм, например
-
Паттерн «объект-форма»
7 паттернов для рефакторинга JavaScript-приложений
-
Паттерн «объект-сервис»
7 паттернов для рефакторинга JavaScript-приложений
-
Паттерн «объект-значение»
7 паттернов для рефакторинга JavaScript-приложений