Код для тестов:
C#:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static int Test(){ var sum = 0; for(var i=0;i<10000000;i++){ sum+=2; } return sum; } static void Main(string[] args) { Applay(); Applay(); if (Console.ReadKey().Key == ConsoleKey.A) Main(new string[]{}); } private static void Applay() { var sw = System.Diagnostics.Stopwatch.StartNew(); Console.WriteLine(Test()); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); } } }
node.js:
const performance = require('perf_hooks').performance; function Test(){ var sum = 0; for(var i=0;i<10000000;i++){ sum+=2; } return sum; } function apply(){ var time = performance.now(); console.log(Test()); time = performance.now()- time; console.log('Время выполнения 1 = ', time); } for (var a=0;a<5;a++){ apply(); }
Система Win7 x32 с предустановленным фреймворком .NET 4.6.1 и node.js 12.2. Результаты:
Итого: node.js уступил немного .NET во времени компиляции, буквально на несколько процентов, и после JIT-компиляции обогнал его почти в 2 раза! Но не спешите с выводами! Тк это неверный бенчмарк? Да. В этом бенчмарке .NET был запущен в Debug режиме. При Realese средняя скорость на .NET составила всего 0.13 мс, так что .NET побеждает. Однако, V8 меня удивил, ибо я ожидал отставания раз в 10 минимум, если не в 100.
Поехали дальше. Попробуем вычислить синус большого числа (бредовое задание, но пусть для проверки):
C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static double Test() { double sum = 0; for (long i = 0; i < 10000000000; i++) { Math.Sin(i); } return sum; } static void Main(string[] args) { Console.ReadLine(); for (int i = 0; i < 5; i++) { Applay(); } Console.ReadKey(); //if (Console.ReadKey().Key == ConsoleKey.A) Main(new string[] { }); } private static void Applay() { var sw = System.Diagnostics.Stopwatch.StartNew(); Test(); //Console.WriteLine(Test()); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); } } }
node.js:
const performance = require('perf_hooks').performance; function Test(){ //var sum = 0; for(var i=0;i<10000000000;i++){ Math.sin(i) } //return sum; } function apply(){ var time = performance.now(); console.log(Test()); time = performance.now()- time; console.log('Время выполнения 1 = ', time); } for (var a=0;a<5;a++){ apply(); }
Результаты:
Здесь тестировался Realese режим C#, тк в Debug время превышало в 20 раз Realese, и я не вижу смысла его приводить. Какие в нем могут быть ошибки? В node можно поставить let вместо var. Вы правы, и я сделал это сразу после того, как заметил. И… результат оказался лучше предыдущего. Судите сами:
Но я бы не сказал однозначно, что он лучше, чем у .NET: только один вызов из пяти оказался быстрее, что похоже на погрешность, и если взять среднее время, то в целом .NET выигрывает около 10-ти процентов процентов и здесь.
Что еще можно. Забыл убрать console.log, который выполняется аж 5 раз. Убрал, и заменил просто на вызов Test()
. Ничего не поменялось (кстати, даже хуже результат — видимо, погрешность оказалась сильнее разницы :)).
Почему ж второй результат у node.js оказался лучше, чем первый, и дышал шарпу почти в затылок? Потому что в js все числа, тип Number, по дефолту представляют из себя 64-битное число с плавающей точкой. и на данный момент там нет возможности управлять типами чисел. Шарп же позволяет оптимизировать свой код, благодаря статической более точной типизации. В остальном можно сказать, что несмотря на небольшую разницу (кстати, если поменять цикл for на while, то результат будет лучше у node, но в среднем не более, чем на 1 мс и хуже, чем аналогичный результат с for на 3мс), оба JIT-компилятора имеют примерно равную очень высокую производительность по работе с числами.
Но несмотря на близость результатов .NET на данный момент, благодаря возможностям более тонкой настройке, позволяет писать более производительные приложения, чем node.js.
Но числа — это не самое главное. Сделаем элементарный тест по работе со строкой:
const performance = require('perf_hooks').performance; function Test(){ let s = "str"; for(let i=0;i<100000;i++){ s.replace('t',''); } } function apply(){ var time = performance.now(); //console.log(Test()); Test(); time = performance.now()- time; console.log('Время выполнения ' + a + ' = ', time); } for (var a=0;a<5;a++){ apply(a); }
Против:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static string Test() { string s = "str"; for(int i=0;i<100000;i++) { s.Replace("t", ""); } return s; } static void Main(string[] args) { Console.ReadLine(); for (int i = 0; i < 5; i++) { Applay(i); } Console.ReadKey(); //if (Console.ReadKey().Key == ConsoleKey.A) Main(new string[] { }); } private static void Applay(int i) { var sw = System.Diagnostics.Stopwatch.StartNew(); Test(); sw.Stop(); Console.WriteLine("Время выполнения " + i + ": " + sw.ElapsedMilliseconds); } } }
Максимальное время выполнения на .NET: 15мс, на node — 47мс. Минимальное на .NET — 13 мс, на node — 37мс.
PS Кстати, решил проверить python на последнем тесте- он традиционно хуже в математике по сравнению с .NET примерно в 1000 раз, но удивительно, что при replace он не уступил ноде (39-41мс):
def main(): s = 'str' for i in range(100000): s.replace('t','') if __name__ == '__main__': import time for i in range(5): start = time.time() main() end = time.time() print(end - start)
Делаем выводы.