В последнее время стали очень популярны тесты производительности JavaScript движков, но в основном они касаются Client Side JavaScript. Меня заинтересовал вопрос: как обстоят дела с Server Side? Но тестировать только Google V8 и SpiderMonkey было бы неинтересно. Ясно, что результаты будут схожи с Client Side — движки-то те же. Поэтому нужно было добавить к тестам что-то, что недоступно в браузере, однако достаточно распространено, а также постараться использовать специфичные для серверных задач тесты. Этим недостающим объектом для тестов виделся компилятор JScript из .Net Framework. Однако предварительные результаты тестов стали сюрпризом для меня, и я решил добавить четвертого игрока из той же команды.
.
Прежде всего, следует сказать, что я не ставил целью 100% объективность тестов. Цель была протестировать движки, которые доступны на расстоянии вытянутой руки (5 минут гугления) и в том окружении, которое доступно мне. А это:
Windows XP SP3 на AMD Sempron 2800+ 1,6GHz 1Gb RAM
Windows 7 x64 на Intel Core i5 650 3,2GHz 4Gb RAM
Несмотря на простоту поставленных задач, получение результата растянулось на несколько дней.
Была избрана простая методика тестирования. Каждый тест представляет собой некую функцию, которая запускается на выполнение в цикле большое количество раз. Замеряется время выполнения всего цикла. Среднее время выполнения каждой итерации берется в качестве критерия оценки. Я не стал следовать принципам статистической достоверности — запускать тесты несколько раз подряд и вычислять средние отклонения. Этот подход, по моему мнению, требует более глубокого анализа, чем просто запуск тестов несколько раз и вычисление средних отклонений.
Для того чтобы оценить, сколько времени в тесте занимает сам цикл, первым тестом будет пустая функция. Кроме того, в свете последних веяний, которые связаны с технологией удаления мертвого кода, хотелось как-то учесть этот фактор в тестах. Мне не пришло в голову ничего лучше, чем выставить требование к тестируемым функциям возвращать некий результат, который основан на том, что делает конкретная функция. Таким образом, у хитрых методик оптимизаций, я надеюсь, не будет оснований выкидывать «нужный» код. Естественно, хитрая оптимизация может выкинуть код на том основании, что результат работы функции не используется далее. Поэтому к каждой тестируемой функции я добавил дополнительный параметр — функцию для агрегации результатов. Сам агрегированный результат тоже будет результатом теста. Чтобы оценить влияние самой агрегации на результат работы цикла, я запускал его еще раз без агрегации. Это также помогает субъективно оценить наличие оптимизации по исключению мертвого кода.
Для удобства запуска тестов и обработки результатов я написал небольшой фреймворк. Кроме того, для однообразного вывода результатов тестов для каждого движка применялся свой модуль-адаптер. Результаты форматировались в html, выводились в консоль и через перенаправление потоков накапливались в едином файле.
Для запуска всего теста использовался небольшой набор CMD файлов.
Первый игрок — это перспективный и набирающий все большую популярность движок Google V8, который работает в Google Chrome, и представлен в тесте в лице не менее перспективного NodeJS. Я был уверен, что результаты тестов не разочаруют меня.
Второй игрок — это достаточно быстрый движок с богатой историей — SpiderMonkey, который работает в FireFox, в тестах он работал в лице JSDB. Тут я тоже не надеялся на какие-то существенные отличия от Client Side тестов.
Третий игрок — компилятор JavaScript от Microsoft. Мне было интересно, какой выигрыш дает использование компилятора, по сравнению с интерпретаторами.
Четвертый игрок — для более полного сравнения хорошо было бы использовать еще интерпретатор от Microsoft.
В случае тестирования интерпретаторов я просто сливал все файлы тестов, фреймворк и адаптеры в один файл командой copy, результирующий файл скармливал интерпретатору. Для NodeJS это nodejs.exe, для JSDB — jsdb.exe, для интерпретатора от Microsoft это Windows Script Host в лице утилиты cscript.exe.
Для компилятора все файлы скармливались jsc.exe из соответствующей версии .Net Framework и запускался результирующий exe файл.
Набор игроков на каждой из платформ отличался.
Да. Я не ошибся. Microsoft JScript 9.0.16406 — это тот самый движок, который используется в IE9. Пришлось немного поколдовать, чтоб заставить работать его в Windows Script Host без установки самого IE9. Я даже не знаю, будет ли он доступен в WSH после установки, поскольку библиотека в установочном пакете называется по-другому и рядом с ней лежит старый движок от IE 8, с нормальным именем.
Под Windows 7 мне был еще доступен компилятор от .NET v.2.0, но тест под ним почему-то вываливался с ошибкой, подробности позже.
Я использовал разные версии движков от Microsoft, чтобы увидеть, есть ли прогресс в скорости от версии к версии и какой. Они лежали у меня «под ногами». Почему бы не включить и их в тест?
Далее для каждого теста буду приводить тестируемую функцию и результаты для среднего времени цикла по всем движкам. Затем все результаты тестов в конце.
тут func — тестируемая функция, reduce — функция-агрегатор, start — стартовое значение агрегатора, loops — количество циклов в тесте.
Результаты Empty test на Windows XP (меньше — лучше)

Результаты Empty test на Windows 7 (меньше — лучше)

Тест типичной операции со строками.
Результаты String Concat на Windows XP (меньше — лучше)

Результаты String Concat на Windows 7 (меньше — лучше)
На мой взгляд типичная для сервера операция.
Результаты Apply template на Windows XP (меньше — лучше)

Результаты Apply template на Windows 7 (меньше — лучше)

Следующие тесты я взял из Google V8 Benchmark Suite version 6.
К сожалению, оказалось, что в этих тестах полно ошибок. На ошибки мне указывал компилятор JScript. Часть ошибок была связана с неполной совместимостью JScript и JavaScript. Часть действительно была ошибками. Я взял 3 теста, которые создавали меньше всего проблем. Немного адаптировал под свой фреймворк, исправил ошибки. Можно было бы взять тесты из Sunspider, но, к сожалению, я не нашел их в виде удобных js исходников. Версия, представленная на сайте с тестом, требует обработки парсером, поскольку встроена в html.
Не буду приводить тут исходники этих тестов — только результаты.
Как сказано на сайте, симулирует работу ядра ОС.
Результаты V8 BS — Richards на Windows XP (меньше — лучше)

Результаты V8 BS — Richards на Windows 7 (меньше — лучше)

Кодирование данных.
Результаты V8 BS — Encrypt на Windows XP (меньше — лучше)

Результаты V8 BS — Encrypt на Windows 7 (меньше — лучше)
Декодирование данных.
Результаты V8 BS — Decrypt на Windows XP (меньше — лучше)

Результаты V8 BS — Decrypt на Windows 7 (меньше — лучше)
Регулярные выражения, извлеченные из 50 популярных сайтов в Интернет.
Результаты V8 BS — RegExp на Windows XP (меньше — лучше)

Результаты V8 BS — RegExp на Windows 7 (меньше — лучше)

Полная таблица результатов на Windows XP.
NodeJS v 0.2.4
Microsoft .NET v.1.1.4322.2032
Microsoft .NET v.2.0.50727.3053
Microsoft .NET v.4.0.30319.1
JSDB 1.8.0.3
Microsoft JScript 5.6.8825
Microsoft JScript 5.7.16599
Microsoft JScript 5.8.18702
Полная таблица результатов на Windows 7.
NodeJS v 0.2.4
JSDB 1.8.0.3
Microsoft .NET v.4.0.30319.1
Microsoft .NET v.4.0.30319.1
Microsoft JScript 5.8.16475
Microsoft JScript 9.0.16406
Компилятор .NET (точнее результаты его работы) оказался самым медленным. Либо я что-то не так делаю, либо он просто ни на что не годен. Интерпретатор от Microsoft версий менее 9-й провалил тест на применение шаблона — результат отличается от остальных. Более внимательное изучение показало, что в нем отличаются назначения параметров функции обратного вызова для replace.
Под Windows 7 не удалось протестировать версию компилятора от .NET Framework 2.0, а версия 4.0 вела себя не менее странно. Тест работал 20 минут. Версия 2.0 вылетала с ошибкой. Для обеих версий тест съедал до 6 Гб памяти. Почему сами тесты показали не такие катастрофические времена? Более внимательное изучение проблемы выявило странную особенность компилятора под Windows 7 x64: проблемы создавал тест V8 BS — Regexp. Причем откомпилированная программа начинала пожирать память еще до начала выполнения моего кода. Похоже .Net как-то инициализирует регулярные выражения, которых в этом тесте в избытке, еще до выполнения кода. Причем проблемы наблюдаются, если регулярные выражения находятся в функции, которая создает замыкание.
Мой окончательный вывод такой: компилятор JScript из .NET Framework ни на что не годен, кроме тестирования кода на ошибки при компиляции. Мне так же стало интересно протестировать, чем будет отличаться С# на подобных задачах. Впрочем, «скоростной» провал JScript .NET начинает проясняться, если посмотреть на трассировку стека при выводе сообщений об ошибках. Такого количества оберток на простых вызовах я еще не видел.
Однако, новый интерпретатор от Microsoft JScript 9.0 вполне конкурентоспособен, его легко расширить своими классами через ActiveScripting. Интересным видится выбор версии. Почему после версии 5.8, которая использовалась в IE8 вдруг вышла версия 9.0? Впрочем, после официального релиза все может поменяться.
Лидер по сокрости Google V8 в NodeJS, но JScript 9.0 наступает на пятки. Мне кажется, что окончательный выбор можно смело делать не только по критерию скорости, а по сумме факторов. В том числе по удобству расширения, отладки, интеграции с платформой.
И в конце — ничего не значащая, чисто иллюстративная диаграмма. Я просто взял отношение времени NodeJS ко времени каждого теста и усреднил по тестам.
Рейтинг движков (больше — лучше)

Ссылки:
NodeJS
JSDB
Google V8 Benchmark Suite version 6
Microsoft Windows Script Host
Microsoft JScript
.
Прежде всего, следует сказать, что я не ставил целью 100% объективность тестов. Цель была протестировать движки, которые доступны на расстоянии вытянутой руки (5 минут гугления) и в том окружении, которое доступно мне. А это:
Windows XP SP3 на AMD Sempron 2800+ 1,6GHz 1Gb RAM
Windows 7 x64 на Intel Core i5 650 3,2GHz 4Gb RAM
Несмотря на простоту поставленных задач, получение результата растянулось на несколько дней.
Методика тестирования
Была избрана простая методика тестирования. Каждый тест представляет собой некую функцию, которая запускается на выполнение в цикле большое количество раз. Замеряется время выполнения всего цикла. Среднее время выполнения каждой итерации берется в качестве критерия оценки. Я не стал следовать принципам статистической достоверности — запускать тесты несколько раз подряд и вычислять средние отклонения. Этот подход, по моему мнению, требует более глубокого анализа, чем просто запуск тестов несколько раз и вычисление средних отклонений.
Для того чтобы оценить, сколько времени в тесте занимает сам цикл, первым тестом будет пустая функция. Кроме того, в свете последних веяний, которые связаны с технологией удаления мертвого кода, хотелось как-то учесть этот фактор в тестах. Мне не пришло в голову ничего лучше, чем выставить требование к тестируемым функциям возвращать некий результат, который основан на том, что делает конкретная функция. Таким образом, у хитрых методик оптимизаций, я надеюсь, не будет оснований выкидывать «нужный» код. Естественно, хитрая оптимизация может выкинуть код на том основании, что результат работы функции не используется далее. Поэтому к каждой тестируемой функции я добавил дополнительный параметр — функцию для агрегации результатов. Сам агрегированный результат тоже будет результатом теста. Чтобы оценить влияние самой агрегации на результат работы цикла, я запускал его еще раз без агрегации. Это также помогает субъективно оценить наличие оптимизации по исключению мертвого кода.
Для удобства запуска тестов и обработки результатов я написал небольшой фреймворк. Кроме того, для однообразного вывода результатов тестов для каждого движка применялся свой модуль-адаптер. Результаты форматировались в html, выводились в консоль и через перенаправление потоков накапливались в едином файле.
Для запуска всего теста использовался небольшой набор CMD файлов.
Игроки
Первый игрок — это перспективный и набирающий все большую популярность движок Google V8, который работает в Google Chrome, и представлен в тесте в лице не менее перспективного NodeJS. Я был уверен, что результаты тестов не разочаруют меня.
Второй игрок — это достаточно быстрый движок с богатой историей — SpiderMonkey, который работает в FireFox, в тестах он работал в лице JSDB. Тут я тоже не надеялся на какие-то существенные отличия от Client Side тестов.
Третий игрок — компилятор JavaScript от Microsoft. Мне было интересно, какой выигрыш дает использование компилятора, по сравнению с интерпретаторами.
Четвертый игрок — для более полного сравнения хорошо было бы использовать еще интерпретатор от Microsoft.
В случае тестирования интерпретаторов я просто сливал все файлы тестов, фреймворк и адаптеры в один файл командой copy, результирующий файл скармливал интерпретатору. Для NodeJS это nodejs.exe, для JSDB — jsdb.exe, для интерпретатора от Microsoft это Windows Script Host в лице утилиты cscript.exe.
Для компилятора все файлы скармливались jsc.exe из соответствующей версии .Net Framework и запускался результирующий exe файл.
Набор игроков на каждой из платформ отличался.
Windows XP
- NodeJS v 0.2.4
- JSDB 1.8.0.3
- Интерпретатор Microsoft JScript 5.6.8825
- Интерпретатор Microsoft JScript 5.7.16599
- Интерпретатор Microsoft JScript 5.8.18702
- Компилятор JScript из Microsoft .NET v.1.1.4322.2032
- Компилятор JScript из Microsoft .NET v.2.0.50727.3053
- Компилятор JScript из Microsoft .NET v.4.0.30319.1
Windows 7
- NodeJS v 0.2.4
- JSDB 1.8.0.3
- Интерпретатор Microsoft JScript 5.8.16475
- Интерпретатор Microsoft JScript 9.0.16406
- Компилятор JScript из Microsoft .NET v.4.0.30319.1
Да. Я не ошибся. Microsoft JScript 9.0.16406 — это тот самый движок, который используется в IE9. Пришлось немного поколдовать, чтоб заставить работать его в Windows Script Host без установки самого IE9. Я даже не знаю, будет ли он доступен в WSH после установки, поскольку библиотека в установочном пакете называется по-другому и рядом с ней лежит старый движок от IE 8, с нормальным именем.
Под Windows 7 мне был еще доступен компилятор от .NET v.2.0, но тест под ним почему-то вываливался с ошибкой, подробности позже.
Я использовал разные версии движков от Microsoft, чтобы увидеть, есть ли прогресс в скорости от версии к версии и какой. Они лежали у меня «под ногами». Почему бы не включить и их в тест?
Тесты
Далее для каждого теста буду приводить тестируемую функцию и результаты для среднего времени цикла по всем движкам. Затем все результаты тестов в конце.
Пустая функция
tests.push({
name: 'Empty test',
func: function(){ return 1;},
reduce: function(r,x){ return r+x;},
start: 0,
loops: 1000000
});
* This source code was highlighted with Source Code Highlighter.
тут func — тестируемая функция, reduce — функция-агрегатор, start — стартовое значение агрегатора, loops — количество циклов в тесте.
Результаты Empty test на Windows XP (меньше — лучше)

Результаты Empty test на Windows 7 (меньше — лучше)

Конкатенация строк
Тест типичной операции со строками.
var str1 = 'Hello ',
str2 = 'world ',
str3 = 'test ',
i = 0;
tests.push({
name: 'String Concat',
func: function(){
i++;
return str1+str2+str3+' '+i;
},
reduce: function(r,x){ return r+x.length;},
start: 0,
loops: 100000
});
* This source code was highlighted with Source Code Highlighter.
Результаты String Concat на Windows XP (меньше — лучше)

Результаты String Concat на Windows 7 (меньше — лучше)

Заполнение шаблона данными
На мой взгляд типичная для сервера операция.
var template = '<html><title>{title}</title><body>{main}</body></html>';
function ApplyTemplate(template, view){
return template.replace(/{(\w+)}/g,function(p,n){
if(n in view) return view[n];
else return '_ERROR_NO_VALUE_'+n;
});
}
var views = [
{
title:'Page One',
main: 'Lorem ipsum dolor sit amet, mauris libero velit, '+
'vitae pellentesque aliquam, cursus magnis velit, non '+
'viverra sed nibh ac fringilla vel, accumsan quis '+
'elementum fermentum ullamcorper. '+
/* ....тут много текста */
'lectus libero at etiam morbi, et orci eros ut sit et.'
},
{
title: 'Page two',
main: 'Short page'
}
];
var counter = 0;
tests.push({
name: 'Apply template',
func: function(){
counter++;
return ApplyTemplate(template, views[counter%2]);
},
reduce: function(r,x){ return r+x.length;},
start: 0,
loops: 10000
});
* This source code was highlighted with Source Code Highlighter.
Результаты Apply template на Windows XP (меньше — лучше)

Результаты Apply template на Windows 7 (меньше — лучше)

Следующие тесты я взял из Google V8 Benchmark Suite version 6.
К сожалению, оказалось, что в этих тестах полно ошибок. На ошибки мне указывал компилятор JScript. Часть ошибок была связана с неполной совместимостью JScript и JavaScript. Часть действительно была ошибками. Я взял 3 теста, которые создавали меньше всего проблем. Немного адаптировал под свой фреймворк, исправил ошибки. Можно было бы взять тесты из Sunspider, но, к сожалению, я не нашел их в виде удобных js исходников. Версия, представленная на сайте с тестом, требует обработки парсером, поскольку встроена в html.
Не буду приводить тут исходники этих тестов — только результаты.
V8 Benchmark Suite Richards
Как сказано на сайте, симулирует работу ядра ОС.
Результаты V8 BS — Richards на Windows XP (меньше — лучше)

Результаты V8 BS — Richards на Windows 7 (меньше — лучше)

V8 Benchmark Suite Encrypt
Кодирование данных.
Результаты V8 BS — Encrypt на Windows XP (меньше — лучше)

Результаты V8 BS — Encrypt на Windows 7 (меньше — лучше)

V8 Benchmark Suite Decrypt
Декодирование данных.
Результаты V8 BS — Decrypt на Windows XP (меньше — лучше)

Результаты V8 BS — Decrypt на Windows 7 (меньше — лучше)

V8 Benchmark Suite RegExp
Регулярные выражения, извлеченные из 50 популярных сайтов в Интернет.
Результаты V8 BS — RegExp на Windows XP (меньше — лучше)

Результаты V8 BS — RegExp на Windows 7 (меньше — лучше)

Полная таблица результатов на Windows XP.
NodeJS v 0.2.4
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 21 | 0.000021 | 44 | 0.000044 | 1000000 |
String Concat | 100000 | 44 | 0.00044 | 47 | 0.00047 | 2288895 |
Apply template | 10000 | 32 | 0.0032 | 28 | 0.0028 | 590000 |
V8 BS — Richards | 1000 | 4879 | 4.879 | 4702 | 4.702 | 0 |
V8 BS — Encrypt | 100 | 345 | 3.45 | 356 | 3.56 | 0 |
V8 BS — Decrypt | 100 | 7496 | 74.96 | 7514 | 75.14 | 0 |
V8 BS — Regexp | 100 | 11620 | 116.2 | 11913 | 119.13 | 0 |
Microsoft .NET v.1.1.4322.2032
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 1891 | 0.001891 | 4094 | 0.004094 | 1000000 |
String Concat | 100000 | 344 | 0.00344 | 859 | 0.00859 | 2288895 |
Apply template | 10000 | 532 | 0.0532 | 609 | 0.0609 | 590000 |
V8 BS — Richards | 25 | 9266 | 370.64 | 9390 | 375.6 | 0 |
V8 BS — Encrypt | 10 | 2875 | 287.5 | 3062 | 306.2 | 0 |
V8 BS — Decrypt | 5 | 33657 | 6731.4 | 32078 | 6415.6 | 0 |
V8 BS — Regexp | 10 | 32296 | 3229.6 | 33219 | 3321.9 | 0 |
Microsoft .NET v.2.0.50727.3053
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 3328 | 0.003328 | 8578 | 0.008578 | 1000000 |
String Concat | 100000 | 515 | 0.00515 | 1297 | 0.01297 | 2288895 |
Apply template | 10000 | 547 | 0.0547 | 657 | 0.0657 | 590000 |
V8 BS — Richards | 25 | 9703 | 388.12 | 9859 | 394.36 | 0 |
V8 BS — Encrypt | 10 | 2531 | 253.1 | 2875 | 287.5 | 0 |
V8 BS — Decrypt | 5 | 25344 | 5068.8 | 25047 | 5009.4 | 0 |
V8 BS — Regexp | 10 | 29032 | 2903.2 | 29234 | 2923.4 | 0 |
Microsoft .NET v.4.0.30319.1
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 2188 | 0.002188 | 5282 | 0.005282 | 1000000 |
String Concat | 100000 | 437 | 0.00437 | 1125 | 0.01125 | 2288895 |
Apply template | 10000 | 500 | 0.05 | 610 | 0.061 | 590000 |
V8 BS — Richards | 25 | 9812 | 392.48 | 10031 | 401.24 | 0 |
V8 BS — Encrypt | 10 | 2719 | 271.9 | 3469 | 346.9 | 0 |
V8 BS — Decrypt | 5 | 28140 | 5628 | 28297 | 5659.4 | 0 |
V8 BS — Regexp | 10 | 34437 | 3443.7 | 33016 | 3301.6 | 0 |
JSDB 1.8.0.3
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 343 | 0.000343 | 719 | 0.000719 | 1000000 |
String Concat | 100000 | 703 | 0.00703 | 547 | 0.00547 | 2288895 |
Apply template | 10000 | 383 | 0.0383 | 233 | 0.0233 | 590000 |
V8 BS — Richards | 1000 | 48319 | 48.319 | 49948 | 49.948 | 0 |
V8 BS — Encrypt | 10 | 905 | 90.5 | 925 | 92.5 | 0 |
V8 BS — Decrypt | 10 | 16571 | 1657.1 | 16475 | 1647.5 | 0 |
V8 BS — Regexp | 10 | 15968 | 1596.8 | 13636 | 1363.6 | 0 |
Microsoft JScript 5.6.8825
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 2578 | 0.002578 | 5812 | 0.005812 | 1000000 |
String Concat | 100000 | 4531 | 0.04531 | 4844 | 0.04844 | 2288895 |
Apply template | 10000 | 1344 | 0.1344 | 1375 | 0.1375 | 410000 |
V8 BS — Richards | 100 | 18484 | 184.84 | 18422 | 184.22 | 0 |
V8 BS — Encrypt | 10 | 1813 | 181.3 | 1797 | 179.7 | 0 |
V8 BS — Decrypt | 10 | 32500 | 3250 | 32187 | 3218.7 | 0 |
V8 BS — Regexp | 10 | 37938 | 3793.8 | 37547 | 3754.7 | 0 |
Microsoft JScript 5.7.16599
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 4235 | 0.004235 | 6562 | 0.006562 | 1000000 |
String Concat | 100000 | 1625 | 0.01625 | 1969 | 0.01969 | 2288895 |
Apply template | 10000 | 562 | 0.0562 | 594 | 0.0594 | 410000 |
V8 BS — Richards | 100 | 22328 | 223.28 | 22625 | 226.25 | 0 |
V8 BS — Encrypt | 10 | 1797 | 179.7 | 1813 | 181.3 | 0 |
V8 BS — Decrypt | 10 | 33953 | 3395.3 | 32219 | 3221.9 | 0 |
V8 BS — Regexp | 10 | 27813 | 2781.3 | 29609 | 2960.9 | 0 |
Microsoft JScript 5.8.18702
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 1171 | 0.001171 | 1532 | 0.001532 | 1000000 |
String Concat | 100000 | 844 | 0.00844 | 1235 | 0.01235 | 2288895 |
Apply template | 10000 | 359 | 0.0359 | 359 | 0.0359 | 410000 |
V8 BS — Richards | 100 | 11906 | 119.06 | 12094 | 120.94 | 0 |
V8 BS — Encrypt | 10 | 1610 | 161 | 1578 | 157.8 | 0 |
V8 BS — Decrypt | 10 | 26875 | 2687.5 | 27281 | 2728.1 | 0 |
V8 BS — Regexp | 10 | 22781 | 2278.1 | 22391 | 2239.1 | 0 |
Полная таблица результатов на Windows 7.
NodeJS v 0.2.4
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 12 | 0.000012 | 14 | 0.000014 | 1000000 |
String Concat | 100000 | 17 | 0.00017 | 13 | 0.00013 | 2288895 |
Apply template | 10000 | 9 | 0.0009 | 11 | 0.0011 | 590000 |
V8 BS — Richards | 1000 | 1640 | 1.64 | 1749 | 1.749 | 0 |
V8 BS — Encrypt | 100 | 120 | 1.2 | 128 | 1.28 | 0 |
V8 BS — Decrypt | 100 | 2570 | 25.7 | 2573 | 25.73 | 0 |
V8 BS — Regexp | 100 | 3996 | 39.96 | 3996 | 39.96 | 0 |
JSDB 1.8.0.3
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 89 | 0.000089 | 221 | 0.000221 | 1000000 |
String Concat | 100000 | 177 | 0.00177 | 167 | 0.00167 | 2288895 |
Apply template | 10000 | 33 | 0.0033 | 33 | 0.0033 | 590000 |
V8 BS — Richards | 1000 | 17738 | 17.738 | 17780 | 17.78 | 0 |
V8 BS — Encrypt | 10 | 272 | 27.2 | 276 | 27.6 | 0 |
V8 BS — Decrypt | 10 | 5095 | 509.5 | 5103 | 510.3 | 0 |
V8 BS — Regexp | 10 | 3454 | 345.4 | 3499 | 349.9 | 0 |
Microsoft .NET v.4.0.30319.1
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 574 | 0.000574 | 1344 | 0.001344 | 1000000 |
String Concat | 100000 | 149 | 0.00149 | 334 | 0.00334 | 2288895 |
Apply template | 10000 | 140 | 0.014 | 281 | 0.0281 | 590000 |
V8 BS — Richards | 25 | 2268 | 90.72 | 2576 | 103.04 | 0 |
V8 BS — Encrypt | 10 | 471 | 47.1 | 2813 | 281.3 | 0 |
V8 BS — Decrypt | 5 | 4908 | 981.6 | 5018 | 1003.6 | 0 |
V8 BS — Regexp | 10 | 8762 | 876.2 | 8805 | 880.5 | 0 |
Microsoft .NET v.4.0.30319.1
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 516 | 0.000516 | 1293 | 0.001293 | 1000000 |
String Concat | 100000 | 118 | 0.00118 | 273 | 0.00273 | 2288895 |
Apply template | 10000 | 136 | 0.0136 | 301 | 0.0301 | 590000 |
V8 BS — Richards | 25 | 2188 | 87.52 | 2477 | 99.08 | 0 |
V8 BS — Encrypt | 10 | 470 | 47 | 3000 | 300 | 0 |
V8 BS — Decrypt | 5 | 4831 | 966.2 | 5049 | 1009.8 | 0 |
V8 BS — Regexp | 10 | 8704 | 870.4 | 8826 | 882.6 | 0 |
Microsoft JScript 5.8.16475
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 244 | 0.000244 | 502 | 0.000502 | 1000000 |
String Concat | 100000 | 168 | 0.00168 | 224 | 0.00224 | 2288895 |
Apply template | 10000 | 90 | 0.009 | 95 | 0.0095 | 410000 |
V8 BS — Richards | 100 | 4391 | 43.91 | 4400 | 44 | 0 |
V8 BS — Encrypt | 10 | 611 | 61.1 | 619 | 61.9 | 0 |
V8 BS — Decrypt | 10 | 10502 | 1050.2 | 10512 | 1051.2 | 0 |
V8 BS — Regexp | 10 | 4768 | 476.8 | 4772 | 477.2 | 0 |
Microsoft JScript 9.0.16406
Name | Loops | Time | Avg | Time wr | Avg wr | Res |
---|---|---|---|---|---|---|
Empty test | 1000000 | 41 | 0.000041 | 82 | 0.000082 | 1000000 |
String Concat | 100000 | 38 | 0.00038 | 39 | 0.00039 | 2288895 |
Apply template | 10000 | 18 | 0.0018 | 17 | 0.0017 | 590000 |
V8 BS — Richards | 100 | 166 | 1.66 | 166 | 1.66 | 0 |
V8 BS — Encrypt | 10 | 15 | 1.5 | 37 | 3.7 | 0 |
V8 BS — Decrypt | 10 | 253 | 25.3 | 246 | 24.6 | 0 |
V8 BS — Regexp | 10 | 3175 | 317.5 | 3188 | 318.8 | 0 |
Выводы
Компилятор .NET (точнее результаты его работы) оказался самым медленным. Либо я что-то не так делаю, либо он просто ни на что не годен. Интерпретатор от Microsoft версий менее 9-й провалил тест на применение шаблона — результат отличается от остальных. Более внимательное изучение показало, что в нем отличаются назначения параметров функции обратного вызова для replace.
Под Windows 7 не удалось протестировать версию компилятора от .NET Framework 2.0, а версия 4.0 вела себя не менее странно. Тест работал 20 минут. Версия 2.0 вылетала с ошибкой. Для обеих версий тест съедал до 6 Гб памяти. Почему сами тесты показали не такие катастрофические времена? Более внимательное изучение проблемы выявило странную особенность компилятора под Windows 7 x64: проблемы создавал тест V8 BS — Regexp. Причем откомпилированная программа начинала пожирать память еще до начала выполнения моего кода. Похоже .Net как-то инициализирует регулярные выражения, которых в этом тесте в избытке, еще до выполнения кода. Причем проблемы наблюдаются, если регулярные выражения находятся в функции, которая создает замыкание.
Мой окончательный вывод такой: компилятор JScript из .NET Framework ни на что не годен, кроме тестирования кода на ошибки при компиляции. Мне так же стало интересно протестировать, чем будет отличаться С# на подобных задачах. Впрочем, «скоростной» провал JScript .NET начинает проясняться, если посмотреть на трассировку стека при выводе сообщений об ошибках. Такого количества оберток на простых вызовах я еще не видел.
Однако, новый интерпретатор от Microsoft JScript 9.0 вполне конкурентоспособен, его легко расширить своими классами через ActiveScripting. Интересным видится выбор версии. Почему после версии 5.8, которая использовалась в IE8 вдруг вышла версия 9.0? Впрочем, после официального релиза все может поменяться.
Лидер по сокрости Google V8 в NodeJS, но JScript 9.0 наступает на пятки. Мне кажется, что окончательный выбор можно смело делать не только по критерию скорости, а по сумме факторов. В том числе по удобству расширения, отладки, интеграции с платформой.
И в конце — ничего не значащая, чисто иллюстративная диаграмма. Я просто взял отношение времени NodeJS ко времени каждого теста и усреднил по тестам.
Рейтинг движков (больше — лучше)

Ссылки:
NodeJS
JSDB
Google V8 Benchmark Suite version 6
Microsoft Windows Script Host
Microsoft JScript