Несподіваний результат тесту на ефективність node.js проти ASP.NET Core


177

Я роблю швидкий стрес-тест для двох (свого роду) привіт світових проектів, написаних і . Обидва вони працюють у виробничому режимі та без приєднаного до них реєстратора. Результат вражає! Ядро ASP.NET перевершує додаток node.js навіть після виконання додаткової роботи, тоді як додаток node.js просто надає подання.

Додаток 1: http://localhost:3000/nodejs node.js

Використання : node.js, двигуна експресу та ваш-рендерінгу.

додаток nodejs

Код у цій кінцевій точці є

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

Як бачите, це не робить нічого, окрім надсилання поточної дати через timeзмінну до перегляду.

Додаток 2: http://localhost:5000/aspnet-core asp.net core

Використання : ASP.NET Core, орієнтація на шаблон за замовчуваннямdnxcore50

Однак це додаток робить щось інше, ніж просто рендерінг сторінки з датою на ній. Він генерує 5 абзаців різних випадкових текстів. Це теоретично повинно зробити це трохи важчим, ніж додаток nodejs.

Основна програма asp.net

Ось метод дій, який відображає цю сторінку

[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();
}

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

Результат стрес-тесту додатків Node.js

Оновлення: За пропозицією Горгі Косева

Використання npm install -g recluster-cli && NODE_ENV=production recluster-cli app.js 8

тест nodejs 2

Результат стрес-тесту ASP.NET Core App

Результат основного стресового тесту asp.net

Не можу повірити своїм очам! Не може бути правдою, що в цьому базовому тесті ядро ​​asp.net набагато швидше, ніж nodejs. Звичайно, це не єдиний показник, який використовується для вимірювання продуктивності між цими двома веб-технологіями, але мені цікаво, що я роблю неправильно на стороні node.js? .

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

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

Оновлення: розподіл у часі програми .NET Core

розподіл часу на додаток aspnetcore

Відповідь сервера

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

52
"Я завжди думав, що node.js швидше, ніж ядро ​​asp.net" - мені цікаво, чому ви так вважаєте? Я не бачив жодних орієнтирів, які б це підтримували (головними причинами, які я чув для прийняття node.js, були "простота використання" та "швидший час розробки / ітерації")
UnholySheep

7
@UnholySheep Це все, що я чув, товариш, я також чув, що це "просто у використанні" і "швидше розвиватися" теж, як правило, від людей, які ніколи не працювали в ASP.NET, особливо в VisualStudio. Я не хвалюся жодними технологіями, - але це така картина, яку я помітив.
визначено

3
У чому тут питання? Якщо це правдоподібно: Так, це так. techempower.com/benchmarks/… .... Також оновіть свою інструментальну ланцюг Dnxcore50 застаріла принаймні на рік-два.
Томас

2
@Tony, використовуючи кластерний модуль, NodeJs породжує декілька робітників, які роблять і поділяють навантаження основного процесу, який прослуховується на одному процесі. Це просто уникає необхідності налаштування декількох додатків у різних портах. Крім того, якщо nodeJs працює в кластерному режимі, тоді має бути стільки ж WebApplications Asp.Net, які працюють в IIS на різних портах, і розподіляти навантаження між ними через деякий балансир навантаження, тоді це буде правильним порівнянням.
Віпреш

36
Node.js чудово підходить для безлічі речей, але швидкість на запит не одна з них. Те, що це найкраще, - це брокер для операцій вводу-виводу через неблокуючу річ-цикл подій, яка, коли Node була новою та блискучою, була великою справою. Звичайно, з тих пір інші мови та рамки наздогнали, тому в .NET у нас є бібліотека паралельних завдань і асинхронний введення / виведення та асинхронізація / очікування. У чому Node не переважає - це такі операції, які пов'язані з процесором, як надання сторінки, оскільки це однопоточний JavaScript.
Марк Rendle

Відповіді:


188

Як багато хто нагадав, порівняння не має контексту.
На момент випуску асинхронний підхід node.js був революційним. З тих пір інші мови та веб-рамки застосовують підходи, які вони застосовували.

Щоб зрозуміти, що означала різниця, вам потрібно змоделювати запит блокування, який представляє деяку завантаженість IO, наприклад запит бази даних. У системі «за потоком на запит» це буде виснажувати нитку потоків, і нові запити будуть поставлені в чергу, очікуючи наявного потоку.
З рамками, що не блокують іо, цього не відбувається.

Розглянемо цей сервер node.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, написаний так, ніби асинхрон / очікування ще не підтримувався, тому датуємо нас назад до ери запуску node.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

Тут немає ніяких сюрпризів, зараз ми відповідаємо node.js.

То що ж це все означає?

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

Якщо ваша мета - це найшвидша обробка окремих запитів, то подивіться на серйозні орієнтири, а не прокатуйте свої власні. Але якщо натомість те, що ви хочете, - це просто те, що відповідає сучасним стандартам, тоді використовуйте будь-яку мову, яка вам подобається, і переконайтеся, що ви не блокуєте ці теми.

Відмова від відповідальності: усі написані коди та запущені тести на старечому MacBook Air під час сонного недільного ранку. Сміливо захопіть код і спробуйте його в Windows або налаштувати на свої потреби - https://github.com/csainty/nodejs-vs-aspnetcore


35
NodeJs ніколи не була унікальною, модель "Нитка на запит" також існувала в Asp.Net до введення nodejs. напр. methodNameAsync
Віпреш

Як наприклад. Ви можете посилатися на цю статтю, пов’язану з операціями з БД, починаючи з 2008 року codedigest.com/Articles/ADO/…
Віпреш,

4
"підходи, які вони застосували", - мало речей унікальних, вони ставлять питання перед значно ширшою аудиторією. Наявність підходу та його запровадження як основний принцип - це дві дуже різні речі.
Кріс Сенті

4
Тут найкраща відповідь. Період.
Нарвалакс

3
@LeeBrindley Я не погоджуюся, це не намагається продемонструвати максимальну пропускну здатність даного обладнання, це демонструє різницю між блокуванням і неблокуванням. Якщо ви хочете порівняти пропускну здатність, я посилаюсь на технологічний апарат.
Кріс Сенті

14

Вузольні рамки, такі як Експрес та Коа, мають жахливі витрати. «Сирий» вузол значно швидший.

Я не пробував цього, але є новіша рамка, яка дуже наближається до продуктивності вузла "Raw": 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

Як бачите, накладні витрати в найпопулярніших структурах node.js ДУЖЕ значні!


5
для чого числа? Чим вище, тим краще?
Іамісті
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.