Node.js与ASP.NET Core性能测试的意外结果


177

我正在用两个(Kinda)Hello World项目编写快速压力测试 。它们都在生产模式下运行,并且没有连接记录器。结果是惊人的!即使做了一些额外的工作,ASP.NET核心仍胜过node.js应用程序,而node.js应用程序仅呈现视图。

应用程式1: http://localhost:3000/nodejs node.js

使用:node.js,express和vash渲染引擎。

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应用压力测试结果

更新:遵循戈尔吉·科塞夫(Gorgi Kosev)的建议

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

nodejs测试2

ASP.NET Core App压力测试结果

asp.net核心压力测试结果

无法相信我的眼睛!在这个基本测试中,asp.net核心要比nodejs快得多是不对的。当然,这并不是衡量这两种Web技术之间性能的唯一指标,但是我想知道在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

51
“我一直认为node.js比asp.net core更快” -我很好奇你为什么这么认为?我还没有看到任何基准可以支持这一点(我听说采用node.js的主要原因是“易于使用”和“更快的开发/迭代时间”)
UnholySheep

7
@UnholySheep这是我所听到的所有内容,我也听说它也是“易于使用”和“开发速度更快”的,通常人们从未使用过ASP.NET,尤其是在VisualStudio中。我不吹牛任何技术-但这是我注意到的模式。
不确定

3
这里有什么问题?如果合理,是的。techempower.com/benchmarks/… ..还更新您的工具链Dnxcore50已经过时了至少一两年。
托马斯

2
@Tony使用集群模块NodeJs产生了多个工作人员,并分担了正在侦听单个进程的主进程的负载。它只是避免了必须在不同的端口上设置多个应用程序。同样,如果nodeJs在群集模式下运行,则在diff端口上的IIS中应有相同数量的Asp.Net WebApplications运行,并通过某个负载平衡器共享它们之间的负载,那么这是正确的比较。
Vipresh

36
Node.js非常适合很多事情,但是每个请求的原始速度并不是其中之一。它的优势是成为I / O操作的代理,这是因为非阻塞事件循环是一件很重要的事情,当Node崭新而闪亮时。当然,从那时起,其他语言和框架也开始流行,因此在.NET中,我们拥有任务并行库,异步I / O和异步/等待。Node不擅长的是CPU约束操作,例如页面渲染,因为它是单线程JavaScript。
马克·雷德尔

Answers:


188

正如许多其他人所提到的,这种比较缺乏上下文。
在发布时,node.js的异步方法是革命性的。从那时起,其他语言和Web框架一直采用它们成为主流的方法。

要了解差异的含义,您需要模拟一个代表某些IO工作负载的阻塞请求,例如数据库请求。在每个请求线程系统中,这将耗尽线程池,并且新请求将放入队列中,以等待可用线程。
使用非阻塞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代码,就好像尚不支持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


34
NodeJ从来都不是唯一的,在引入nodejs之前,Asp.Net中还存在基于每个请求的线程模型。所有执行I / O的方法都有Framework提供的2个版本的sync和Asynchronous,它们的ASYNC方法以关键字“ Async”结尾例如。methodNameAsync
Vipresh

作为一个例子。您可以参考这篇与数据库操作有关的文章,该文章可以追溯到2008codedigest.com/Articles/ADO/…–
Vipresh

4
“他们采取的主流方法”-很少有什么独特之处,他们将这个问题摆在了更广泛的读者面前。有一种可用的方法,并将其作为核心原则,是两件截然不同的事情。
克里斯·桑迪

4
最好的答案在这里。期。
Narvalex

3
@LeeBrindley我不同意,这并不是要演示给定硬件的最大吞吐量,而是要说明阻塞与非阻塞之间的区别。如果您想进行原始吞吐量比较,请链接至techempower。
克里斯·桑迪

14

诸如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

如您所见,最流行的node.js框架中的开销非常大!


5
这些数字是什么?越高越好?
Iamisti '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.