Неожиданный исход узла.js vs ASP.NET проверка производительности ядра


я делаю быстрый стресс-тест на двух (своего рода) hello world проектов, написанных в узел.js и asp.net-core. оба они работают в рабочем режиме и без подключенного к ним регистратора. Результат поразительный! ASP.NET ядро опережает узел.js приложение даже после выполнения некоторых дополнительных работ в то время как узел.приложение js просто отображает представление.

Приложение 1: http://localhost:3000/nodejsnode.js

используя: узел.Яш, экспресс и ваш движок.

код в этой конечной точки

router.get('/', function(req, res, next) {
  var vm = {
    title: 'Express',
    time: new Date()
  }
  res.render('index', vm);
});

как вы можете видеть, он ничего не делает, кроме отправки текущей даты через time переменная для представления.

Приложение 2: http://localhost:5000/aspnet-coreasp.net core

используя: ASP.NET ядро, шаблон по умолчанию таргетинг dnxcore50

однако это приложение делает что-то другое, чем просто рендеринг страницы с датой на нем. Он генерирует 5 абзацы различных случайных текстов. Это теоретически должно сделать это немного тяжелее, чем приложение nodejs.

вот метод действия, который отображает эту страницу

[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("aspnet-core")]
public IActionResult Index()
{
    var sb = new StringBuilder(1024);
    GenerateParagraphs(5, sb);

    ViewData["Message"] = sb.ToString();
    return View();
}

результат стресс-теста

узел.результат стресс-теста js App

обновление: следуя предложению Горги Косева

используя npm install -g recluster-cli && NODE_ENV=production recluster-cli app.js 8

ASP.NET Основной результат стресс-теста приложения

не могу поверить своим глазам! Это не может быть правдой, что в этом базовом тесте asp.net ядро намного быстрее, чем nodejs. Конечно, это не единственная метрика, используемая для измерения производительности между этими двумя веб-технологиями, но мне интересно что я делаю неправильно в узле.js сторона?.

быть профессионалом asp.net разработчик и желающий адаптировать узел.js в личных проектах, это своего рода кое - как я немного обеспокоен производительности. Я думал, узел.js быстрее, чем asp.net ядро (в целом-как видно из различных других тестов) я просто хочу доказать это себе (чтобы побудить себя к адаптации узла.js).

пожалуйста, ответьте в комментарии, если вы хотите, чтобы включить больше фрагментов кода.

обновление: распределение времени .NET Core app

сервер ответ

HTTP/1.1 200 OK
Cache-Control: no-store,no-cache
Date: Fri, 12 May 2017 07:46:56 GMT
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Kestrel
2 117

2 ответа:

как и многие другие упоминали, сравнение не имеет контекста.
На момент его выпуска, асинхронный подход узла.JS был революционером. С тех пор другие языки и веб-фреймворки принимают подходы, которые они приняли в основном.

чтобы понять, что означает разница, вам нужно смоделировать запрос блокировки, который представляет некоторую рабочую нагрузку ввода-вывода, такую как запрос базы данных. В системе thread-per-request это приведет к исчерпанию пула потоков и новых запросов будет помещен в очередь, ожидающую доступного потока.
С неблокирующими фреймворками io этого не происходит.

рассмотреть этот узел.сервер JS, который ждет 1 секунду, прежде чем ответить

const server = http.createServer((req, res) => {
  setTimeout(() => {
    res.statusCode = 200;
    res.end();
  }, 1000);
});

теперь давайте бросим 100 параллельных конценций на него, за 10 С. Таким образом, мы ожидаем около 1000 запросов для завершения.

$ wrk -t100 -c100 -d10s http://localhost:8000
Running 10s test @ http://localhost:8000
  100 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.01s    10.14ms   1.16s    99.57%
    Req/Sec     0.13      0.34     1.00     86.77%
  922 requests in 10.09s, 89.14KB read
Requests/sec:     91.34
Transfer/sec:      8.83KB

как вы можете видеть, мы получаем в футбольном поле с 922 завершена.

теперь рассмотрим следующее asp.net код, написанный как бы async/await еще не поддерживались,поэтому мы возвращаемся к узлу.эра запуска js.

app.Run((context) =>
{
    Thread.Sleep(1000);
    context.Response.StatusCode = 200;
    return Task.CompletedTask;
});

$ wrk -t100 -c100 -d10s http://localhost:5000
Running 10s test @ http://localhost:5000
  100 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.08s    74.62ms   1.15s   100.00%
    Req/Sec     0.00      0.00     0.00    100.00%
  62 requests in 10.07s, 5.57KB read
  Socket errors: connect 0, read 0, write 0, timeout 54
Requests/sec:      6.16
Transfer/sec:     566.51B

62! Здесь мы видим предел пула потоков. Настроив его, мы могли бы получить больше параллельных запросов, но за счет большего количества ресурсов сервера.

для этих рабочих нагрузок, связанных с IO, перемещение, чтобы избежать блокировки потоков обработки, было настолько драматичным.

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

app.Run(async (context) =>
{
    await Task.Delay(1000);
    context.Response.StatusCode = 200;
});

$ wrk -t100 -c100 -d10s http://localhost:5000
Running 10s test @ http://localhost:5000
  100 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.01s    19.84ms   1.16s    98.26%
    Req/Sec     0.12      0.32     1.00     88.06%
  921 requests in 10.09s, 82.75KB read
Requests/sec:     91.28
Transfer/sec:      8.20KB

никаких сюрпризов здесь, мы теперь совпадаем узел.js.

так что же все это значит?

ваши впечатления, что узел.js - это "самый быстрый" выход из эпохи, в которой мы больше не живем. Добавьте к этому, что это никогда не было node/js/v8, которые были "быстрыми", это было то, что они сломали модель потока на запрос. Все остальные уже подтягиваются.

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

отказ от ответственности: весь написанный код и тесты выполняются на стареющем MacBook Air во время сонного воскресного утра. Не стесняйтесь захватить код и попробовать его на Windows или настроить под свои нужды - https://github.com/csainty/nodejs-vs-aspnetcore

узловые структуры, такие как Express и Koa, имеют ужасные накладные расходы. "Сырой" узел работает значительно быстрее.

Я не пробовал, но есть новая структура, которая очень близка к" сырой " производительности узла:https://github.com/aerojs/aero

(см. Тест на этой странице)

обновление: вот некоторые цифры:https://github.com/blitzprog/webserver-benchmarks

Node:
    31336.78
    31940.29
Aero:
    29922.20
    27738.14
Restify:
    19403.99
    19744.61
Express:
    19020.79
    18937.67
Koa:
    16182.02
    16631.97
Koala:
    5806.04
    6111.47
Hapi:
    497.56
    500.00

Как вы можете видеть, накладные расходы в самый популярный узел.рамки js очень значительны!