web-dev-qa-db-ja.com

Node.jsとASP.NET Coreのパフォーマンテストの予想外の結果

node.jsasp.net-core で書かれた2つの(ちょっと)hello worldプロジェクトで簡単なストレステストを行っています。どちらもプロダクションモードで動作しており、ロガーは接続されていません。結果は驚くべきことです。 node.jsアプリは単にビューをレンダリングしているのに対し、ASP.NETコアは追加の作業をした後でもnode.jsアプリより優れています。

アプリ1:http://localhost:3000/nodejsnode.js

:node.js、expressおよびvashレンダリングエンジンを使用します。

nodejs app

このエンドポイントのコードは

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 Core、デフォルトのテンプレートターゲティングdnxcore50

ただし、このアプリでは、日付のあるページをレンダリングするだけではありません。それは様々なランダムなテキストの5段落を生成します。これは理論的にはnodejsアプリよりも少し重くなります。

asp.net core app

これはこのページをレンダリングするアクションメソッドです。

[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アプリストレステスト結果

更新: Gorgi Kosevによる提案の後に

npm install -g recluster-cli && NODE_ENV=production recluster-cli app.js 8を使う

nodejs test 2

ASP.NET Core Appストレステストの結果

asp.net core stress test result

私の目を信じることができない!この基本的なテストでは、asp.netのコアがnodejsよりもはるかに高速であることは事実ではありません。もちろん、これはこれら2つのWebテクノロジ間のパフォーマンスを測定するために使用される唯一の測定基準ではありませんが、私は疑問に思っています node.js側で何が間違っているのですか?

プロのasp.net開発者であり、個人的なプロジェクトにnode.jsを適応させたいと思っているので、これは私を遅らせるようなものです - 私はパフォーマンスについて少し妄想的です。 node.jsはasp.netコアよりも速いと思いました(一般的に - 他のさまざまなベンチマークで見られるように)私はそれを自分自身に証明したいだけです(node.jsを適応させるために自分を励ますため)。

もっとコードスニペットを追加してほしい場合は、コメントで返信してください。

更新: .NET Coreアプリの時間分布

aspnetcore app time distribution

サーバーの応答

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
144
undefined

他の多くの人が暗示しているように、この比較には文脈が欠けています。
リリース時点で、node.jsの非同期アプローチは革命的でした。それ以来、他の言語やWebフレームワークは、それらが主流を取ったアプローチを採用しています。

その違いが何を意味するのかを理解するには、データベース要求などのIOワークロードを表すブロッキング要求をシミュレートする必要があります。要求ごとのスレッドシステムでは、これはスレッドプールを使い果たし、新しい要求は利用可能なスレッドを待っているキューに入れられます。
non-blocking-ioフレームワークではこれは起こりません。

応答する前に1秒待つこのnode.jsサーバーを考えてください。

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が完成した状態で球場に入ります。

Async/awaitがまだサポートされていないかのように書かれた、次のasp.netのコードを考えてみましょう。

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が「最速」であるというあなたの印象は、私たちがもう住んでいない時代から来ています。それに加えて、「高速」であったのは決してnode/js/v8ではありませんでした。モデル。他の誰もが追いついています。

あなたの目標が単一のリクエストの最も速い処理であるならば、あなた自身のものを転がす代わりに 深刻なベンチマーク を見てください。しかし、その代わりにあなたが望むものが現代の標準に合わせたものであれば、どちらの言語を選んでもそれらのスレッドをブロックしていないことを確認してください。

免責事項:すべてのコードが書かれており、テストは眠い日曜日の朝にMacBook Air上で実行されます。コードを入手してWindowsで試すか、必要に応じて微調整してください - https://github.com/csainty/nodejs-vs-aspnetcore

153
Chris Sainty

ExpressやKoaのようなノードフレームワークはひどいオーバーヘッドを抱えています。 「Raw」ノードはかなり高速です。

試したことはありませんが、「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フレームワークのオーバーヘッドは非常に重要です。

9
smorgs