node.js与ASP.NET Core性能testing的意外结果

我正在用node.js和asp.net-core编写的两个(有点)hello世界项目做一个快速压力testing。 他们都在生产模式下运行,没有logging器连接到他们。 结果是惊人的! 即使在做了一些额外的工作之后,ASP.NET核心的performance也优于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); }); 

正如你所看到的,除了通过timevariables发送当前date到视图之外,它什么都不做。

应用程序2: http://localhost:5000/aspnet-core asp.net core

使用 :ASP.NET核心,默认模板定位dnxcore50

然而,这个应用程序不只是呈现一个页面上的date。 它生成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(); } 

压力testing结果

Node.js应用程序压力testing结果

更新: Gorgi Kosev的build议

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

nodejs测试2

ASP.NET Core App压力testing结果

asp.net核心压力测试结果

不敢相信我的眼睛! 在这个基本的testing中,asp.net核心比nodejs要快得多。 当然,这不是衡量这两种Web技术之间性能的唯一指标,但是我想知道我在node.js方面做了什么错误?

作为一名专业的asp.net开发人员,希望能够在个人项目中使用node.js,这有点让我失望 – 因为我对性能有点偏执。 我认为node.js比asp.net核心更快(一般来说 – 正如其他各种基准testing中所见),我只是想自己certificate一下(以鼓励自己适应node.js)。

如果您希望我添加更多的代码片段,请回复评论。

更新: .NET核心应用程序的时间分布

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 

       

网上收集的解决方案 "node.js与ASP.NET Core性能testing的意外结果"

正如其他许多人所暗示的那样,这种比较缺乏语境。
在发布的时候,node.js的asynchronous方法是革命性的。 从那时起,其他语言和网页框架就采用了他们主stream的方法。

为了理解这个区别是什么意思,你需要模拟代表一些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代码,尽pipeasync / 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是“快”的,它们是打破了每个请求的线程模型。 其他人一直在追赶。

如果您的目标是尽可能快地处理单个请求,那么请查看严重的基准testing,而不是自行testing。 但是,如果你想要的东西只是按照现代标准进行扩展的东西,那就select你喜欢的任何一种语言,并确保你没有阻止那些线程。

免责声明:所有的代码都是在星期天早上的昏昏欲睡的MacBook Air上写下来的,并进行testing。 随意获取代码,并在Windows上尝试或调整您的需求 – https://github.com/csainty/nodejs-vs-aspnetcore

负载下的执行速度和缩放比例是有区别的。 如果你正在寻找执行的速度,这是你在这里看到的,你会发现一些更快的语言和框架 – Java是其中之一,最有可能的是,在顶部。 C#和.NET也非常快。

缩放是一个完全不同的问题,并且是由于它的asynchronous性质,Node擅长的地方。 它不会阻塞主线程,并允许一次发生多个事件。 与其他许多框架一样,ASP.NET也是如此(使用async / await)。 这不是那个小说,真的。

节点的声誉是从来没有速度,这是缩放 。 你可以用廉价而快速的方式来做事情,一般来说,它比当时stream行的框架,比如Ruby on Rails,要好得多。

最后:基准testing很难做到正确。 一次这样的testing基本上是没有意义的。 这不会改变我上面写的东西,但是。

像Express和Koa这样的Node框架有一个可怕的开销。 “原始”节点显着更快。

我还没有尝试过,但有一个更新的框架,非常接近“原始”节点的性能: 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 

正如您所看到的,最stream行的node.js框架中的开销非常重要!