1. ホーム
  2. c#

[解決済み】node.js vs ASP.NET Core パフォーマンステストの予期せぬ結果

2022-04-17 16:34:53

質問

で書かれた2つの(一種の)hello worldプロジェクトで簡単なストレステストを行っています。 node.js asp.net-コア . どちらも本番モードで、ロガーを付けずに動作させています。結果は驚くべきものでした。ASP.NET core は、node.js アプリが単にビューをレンダリングしているのに対して、いくつかの追加作業を行った後でも node.js アプリより性能が高いのです。

アプリ1 http://localhost:3000/nodejs node.js

使用方法 : node.js、express、vashレンダリングエンジン。

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

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のアプリより少し重くなるはずです。

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

[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

ASP.NET Coreアプリストレステスト結果

自分の目を疑うような光景です。この基本的なテストでは、asp.net coreがnodejsよりずっと速いというのはありえないことです。もちろん、この2つのウェブテクノロジーのパフォーマンスを測定するために使用される唯一の指標ではありませんが、私は不思議に思っています。 node.js側で何か間違ったことをしているのでしょうか? .

私はプロのasp.net開発者であり、個人的なプロジェクトにnode.jsを適応させたいと考えています。私はnode.jsがasp.net coreより速いと思っていました(一般的に - 他の様々なベンチマークで見られるように)私はちょうど自分自身にそれを証明したい(node.jsを適応する際に自分自身を奨励するために)。

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

更新しました。 .NET Coreアプリの時間配分

サーバーの応答

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

解決方法は?

他の多くの人が言及しているように、この比較は文脈を欠いています。

リリース当時、node.jsの非同期アプローチは画期的でした。それ以来、他の言語やウェブフレームワークは、彼らが主流としたアプローチを採用しています。

この違いが何を意味するのかを理解するためには、データベースへのリクエストなど、何らかのIOワークロードを表すブロッキングリクエストをシミュレートする必要があります。スレッドパーリクエストシステムでは、これはスレッドプールを使い果たし、新しいリクエストは利用可能なスレッドを待つキューに入れられることになります。

ノンブロッキングIOのフレームワークでは、このようなことは起こりません。

応答する前に1秒待つnode.jsサーバーを考えてみましょう。

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

では、10秒間、100の同時接続を投げてみましょう。つまり、約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 がまだサポートされていないため、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が最速というのは、もはや私たちが生きていない時代から来た印象です。さらに、node/js/v8が「速い」のではなく、スレッド・パー・レクエスト・モデルを打ち破ったのです。他の誰もが追いついてきたのです。

単一リクエストの最速処理が目的なら シリアスベンチマーク 自前で開発するのではなく しかし、その代わりに、単に現代の標準に合うようなスケーラビリティを求めるのであれば、好きな言語を選び、スレッドをブロックしないように注意してください。

免責事項: すべてのコードは、古いMacBook Airで書かれ、テストは眠い日曜日の朝に実行されました。Windowsで試してみたり、あなたのニーズに合わせて微調整するのはご自由にどうぞ。 https://github.com/csainty/nodejs-vs-aspnetcore