Node.js 与 .Net 性能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9290160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:11:31  来源:igfitidea点击:

Node.js vs .Net performance

.netperformancenode.js

提问by David Merrilees

I've read a lot about Node.js being fast and able to accommodate large amounts of load. Does anyone have any real world evidence of this vs other frameworks, particularly .Net? Most of the articles i've read are anecdotal or don't have comparisons to .Net.

我已经阅读了很多关于 Node.js 速度快并且能够适应大量负载的信息。有没有人有任何真实世界的证据证明这个与其他框架相比,特别是 .Net?我读过的大多数文章都是轶事,或者没有与 .Net 进行比较。

Thanks

谢谢

回答by Matt Dotson

Being FASTand handling lots of LOADare two different things. A server that's really FASTat serving one request per second might totally croak if you send it 500 requests per second (under LOAD).

作为FAST和处理大量的负载是两回事。如果您每秒发送 500 个请求(在LOAD下),那么每秒处理一个请求的速度非常快的服务器可能会完全崩溃。

You also have to consider static (and cached) vs dynamic pages. If you're worried about static pages, then IIS is probably going to beat node because IIS uses kernel-mode caching, which means that requests which request a static page are not even going to get out of the kernel.

您还必须考虑静态(和缓存)页面与动态页面。如果您担心静态页面,那么 IIS 可能会击败节点,因为 IIS 使用内核模式缓存,这意味着请求静态页面的请求甚至不会离开内核。

I'm guessing that you're looking for a comparison between ASP.NET and node. In this battle, after everything's been compiled/interpreted you're probably going to be pretty close in performance. Maybe .NET's a little FASTERor maybe node's a little FASTER, but it's probably close enough that you don't care. I'd bet on .NET, but I don't know for sure.

我猜您正在寻找 ASP.NET 和 node.js 之间的比较。在这场战斗中,在编译/解释完所有内容之后,您的性能可能会非常接近。也许 .NET 有点快,或者 node 有点,但它可能足够接近以至于你不在乎。我打赌 .NET,但我不确定。

The place that node is really compelling is for handling LOAD. This is where the technologies really differ. ASP.NET dedicates a thread for each request from its thread pool, and once ASP.NET has exhausted all the available threads requests begin to get queued up. If you're serving "Hello World" apps like the example by @shankar, then this might not matter that much because the threads aren't going to be blocked and you're going to be able to handle a lot of requests before you run out of threads. The problem with the ASP.NET model comes when you start making I/O requests that block the thread (call to a DB, make an http request to a service, read a file from disk). These blocking requests mean that your valuable thread from the thread pool is doing nothing. The more blocking you have, the less LOADyour ASP.NET app is going to be able to serve.

node 真正引人注目的地方是处理LOAD。这就是技术真正不同的地方。ASP.NET 为其线程池中的每个请求指定一个线程,一旦 ASP.NET 耗尽所有可用线程,请求就会开始排队。如果您正在为@shankar 的示例提供“Hello World”应用程序,那么这可能无关紧要,因为线程不会被阻塞,并且您将能够在您之前处理大量请求线程用完。当您开始发出阻塞线程的 I/O 请求(调用 DB、向服务发出 http 请求、从磁盘读取文件)时,ASP.NET 模型就会出现问题。这些阻塞请求意味着线程池中有价值的线程什么都不做。你的阻塞越多,加载您的 ASP.NET 应用程序将能够提供服务。

To prevent this blocking, you use I/O completion ports which don't require holding a thread while you wait for a response. ASP.NET supports this, but unfortunately many of the common frameworks/libraries in .NET DON'T. For example, ADO.NET supports I/O completion ports, but Entity Framework doesn't use them. So you can build an ASP.NET app that's purely asynchronous and handles lots of load, but most people don't because it isn't as easy as building one that's synchronous, and you might not be able to use some of your favorite parts of the framework (like linq to entities) if you do.

为了防止这种阻塞,您使用 I/O 完成端口,在等待响应时不需要保持线程。ASP.NET 支持这一点,但不幸的是,.NET 中的许多常见框架/库不支持。例如,ADO.NET 支持 I/O 完成端口,但实体框架不使用它们。因此,您可以构建一个纯异步并处理大量负载的 ASP.NET 应用程序,但大多数人不会这样做,因为它不像构建一个同步应用程序那么容易,而且您可能无法使用一些您喜欢的部分框架(如 linq 到实体),如果你这样做。

The problem is that ASP.NET (and the .NET Framework) were created to be un-opinionated about asynchronous I/O. .NET doesn't care if you write synchronous or asynchronous code, so it's up to the developer to make this decision. Part of this is because threading and programming with asynchronous operations was thought to be "hard", and .NET wanted to make everyone happy (noobs and experts). It got even harder because .NET ended up with 3-4 different patterns for doing async. .NET 4.5 is trying to go back and retrofit the .NET framework to have an opinionated model around async IO, but it may be a while until the frameworks you care about actually support it.

问题是 ASP.NET(和 .NET Framework)被创建为对异步 I/O 没有意见。.NET 并不关心您是编写同步代码还是异步代码,因此由开发人员来做出这个决定。部分原因是因为线程和异步操作编程被认为是“困难的”,而 .NET 想让每个人都开心(新手和专家)。它变得更加困难,因为 .NET 最终有 3-4 种不同的异步模式。.NET 4.5 正试图回过头来改造 .NET 框架以拥有一个围绕异步 IO 的自以为是的模型,但可能需要一段时间才能让您关心的框架真正支持它。

The designers of node on the other hand, made an opinionated choice that ALL I/O should be async. Because of this decision, node designers were also able to make the decision that each instance of node would be single threaded to minimize thread switching, and that one thread would just execute code that had been queued. That might be a new request, it might be the callback from a DB request, it might be the callback from a http rest request you made. Node tries to maximize CPU efficiency by eliminating thread context switches. Because node made this opinionated choice that ALL I/O is asynchronous, that also means that all it's frameworks/add-ons support this choice. It's easier to write apps that are 100% async in node (because node forces you to write apps that are async).

另一方面,节点的设计者做出了一个固执的选择,即所有 I/O 都应该是异步的。由于这一决定,节点设计者还能够决定节点的每个实例都将是单线程的,以最大限度地减少线程切换,并且一个线程将只执行已排队的代码。这可能是一个新请求,可能是来自 DB 请求的回调,也可能是来自您发出的 http rest 请求的回调。Node 试图通过消除线程上下文切换来最大化 CPU 效率。因为 node 做出了所有 I/O 都是异步的这个固执的选择,这也意味着它的所有框架/附加组件都支持这个选择。在 node 中编写 100% 异步的应用程序更容易(因为 node 强制您编写异步的应用程序)。

Again, I don't have any hard numbers to prove one way or another, but I think node would win the LOAD competition for the typical web app. A highly optimized (100% async) .NET app might give the equivalent node.js app a run for it's money, but if you took an average of all the .NET and all the node apps out there, on average node probably handles more LOAD.

同样,我没有任何硬性数字来证明一种或另一种方式,但我认为 node 会赢得典型 Web 应用程序的 LOAD 竞争。一个高度优化(100% 异步)的 .NET 应用程序可能会让等效的 node.js 应用程序物有所值,但如果你取所有 .NET 和所有节点应用程序的平均值,平均节点可能会处理更多加载。

Hope that helps.

希望有帮助。

回答by Shankar

I did a rudimentary performance test between nodejs and IIS. IIS is about 2.5 times faster than nodejs when dishing out "hello, world!". code below.

我在 nodejs 和 IIS 之间做了一个基本的性能测试。IIS 在发出“hello, world!”时大约比 nodejs 快 2.5 倍。下面的代码。

my hardware: Dell Latitude E6510, Core i5 (dual core), 8 GB RAM, Windows 7 Enterprise 64 bit OS

我的硬件:Dell Latitude E6510、Core i5(双核)、8 GB RAM、Windows 7 Enterprise 64 位操作系统

node server

节点服务器

runs at http://localhost:9090/
/// <reference path="node-vsdoc.js" />
var http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, { "Content-Type": "text/html" });
response.write("<p>hello, world!</p>");
response.end();
}).listen(9090);

default.htm

默认.htm

hosted by iis at http://localhost/test/
<p>hello, world!</p>

my own benchmark program using task parallel library:

我自己的基准程序使用任务并行库:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;

namespace HttpBench
{
class Program
{
    private int TotalCount = 100000;
    private int ConcurrentThreads = 1000;
    private int failedCount;
    private int totalBytes;
    private int totalTime;
    private int completedCount;
    private static object lockObj = new object();

    /// <summary>
    /// main entry point
    /// </summary>
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run(args);
    }

    /// <summary>
    /// actual execution
    /// </summary>
    private void Run(string[] args)
    {
        // check command line
        if (args.Length == 0)
        {
            this.PrintUsage();
            return;
        }
        if (args[0] == "/?" || args[0] == "/h")
        {
            this.PrintUsage();
            return;
        }

        // use parallel library, download data
        ParallelOptions options = new ParallelOptions();
        options.MaxDegreeOfParallelism = this.ConcurrentThreads;
        int start = Environment.TickCount;
        Parallel.For(0, this.TotalCount, options, i =>
            {
                this.DownloadUrl(i, args[0]);
            }
        );
        int end = Environment.TickCount;

        // print results
        this.Print("Total requests sent: {0}", true, this.TotalCount);
        this.Print("Concurrent threads: {0}", true, this.ConcurrentThreads);
        this.Print("Total completed requests: {0}", true, this.completedCount);
        this.Print("Failed requests: {0}", true, this.failedCount);
        this.Print("Sum total of thread times (seconds): {0}", true, this.totalTime / 1000);
        this.Print("Total time taken by this program (seconds): {0}", true, (end - start) / 1000);
        this.Print("Total bytes: {0}", true, this.totalBytes);
    }

    /// <summary>
    /// download data from the given url
    /// </summary>
    private void DownloadUrl(int index, string url)
    {
        using (WebClient client = new WebClient())
        {
            try
            {
                int start = Environment.TickCount;
                byte[] data = client.DownloadData(url);
                int end = Environment.TickCount;
                lock (lockObj)
                {
                    this.totalTime = this.totalTime + (end - start);
                    if (data != null)
                    {
                        this.totalBytes = this.totalBytes + data.Length;
                    }
                }
            }
            catch
            {
                lock (lockObj) { this.failedCount++; }
            }
            lock (lockObj)
            {
                this.completedCount++;
                if (this.completedCount % 10000 == 0)
                {
                    this.Print("Completed {0} requests.", true, this.completedCount);
                }
            }
        }
    }

    /// <summary>
    /// print usage of this program
    /// </summary>
    private void PrintUsage()
    {
        this.Print("usage: httpbench [options] <url>");
    }

    /// <summary>
    /// print exception message to console
    /// </summary>
    private void PrintError(string msg, Exception ex = null, params object[] args)
    {
        StringBuilder sb = new System.Text.StringBuilder();
        sb.Append("Error: ");
        sb.AppendFormat(msg, args);
        if (ex != null)
        {
            sb.Append("Exception: ");
            sb.Append(ex.Message);
        }
        this.Print(sb.ToString());
    }

    /// <summary>
    /// print to console
    /// </summary>
    private void Print(string msg, bool isLine = true, params object[] args)
    {
        if (isLine)
        {
            Console.WriteLine(msg, args);
        }
        else
        {
            Console.Write(msg, args);
        }
    }

}
}

and results:

和结果:

IIS: httpbench.exe http://localhost/test

Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 97
Total time taken by this program (seconds): 16
Total bytes: 2000000

nodejs: httpbench.exe http://localhost:9090/

Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 234
Total time taken by this program (seconds): 27
Total bytes: 2000000

conclusion: IIS is faster than nodejs by about 2.5 times (on Windows). This is a very rudimentary test, and by no means conclusive. But I believe this is a good starting point. Nodejs is probably faster on other web servers, on other platforms, but on Windows IIS is the winner. Developers looking to convert their ASP.NET MVC to nodejs should pause and think twice before proceeding.

结论:IIS 比 nodejs 快约 2.5 倍(在 Windows 上)。这是一个非常基本的测试,绝不是决定性的。但我相信这是一个很好的起点。Nodejs 在其他 Web 服务器和其他平台上可能更快,但在 Windows 上 IIS 是赢家。希望将他们的 ASP.NET MVC 转换为 nodejs 的开发人员应该在继续之前暂停并三思。

Updated (5/17/2012) Tomcat (on windows) seems to beat IIS hands down, about 3 times faster than IIS in dishing out static html.

更新(2012 年 5 月 17 日)Tomcat(在 Windows 上)似乎击败了 IIS,在输出静态 html 方面比 IIS 快约 3 倍。

tomcat

公猫

index.html at http://localhost:8080/test/
<p>hello, world!</p>

tomcat results

tomcat 结果

httpbench.exe http://localhost:8080/test/
Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 31
Total time taken by this program (seconds): 5
Total bytes: 2000000

updated conclusion: i ran the benchmark program multiple times. Tomcat appears to be the fastest server in dishing out STATIC HTML, ON WINDOWS.

更新的结论:我多次运行基准程序。Tomcat 似乎是在 WINDOWS 上发布 STATIC HTML 的最快服务器。

Updated (5/18/2012) Previously I had 100,000 total requests with 10,000 concurrent requests. I increased it to 1,000,000 total requess and 100,000 concurrent requests. IIS comes out as the screaming winner, with Nodejs fairing the worst. I have tabularized the results below:

更新 (5/18/2012) 以前我有 100,000 个总请求和 10,000 个并发请求。我将其增加到 1,000,000 个总请求和 100,000 个并发请求。IIS 脱颖而出,成为尖叫的赢家,而 Nodejs 表现最差。我已将结果列表如下:

NodeJS vs IIS vs Tomcat serving STATIC HTML on WINDOWS.

NodeJS vs IIS vs Tomcat 在 WINDOWS 上提供静态 HTML.

回答by ttekin

NIO servers (Node.js etc) tend to be faster than BIO servers. (IIS etc). To back my claim, TechEmpower is a company specialized on web framework benchmarks. They are very open and have a standard way of testing all framewrks.

NIO 服务器(Node.js 等)往往比 BIO 服务器更快。(IIS 等)。为了支持我的说法,TechEmpower 是一家专门从事Web 框架基准测试的公司。它们非常开放,并且具有测试所有框架的标准方法。

Round 9 tests are currently the latest (May 2014). There are many IIS flavors tested, but aspnet-stripped seems to be the fastest IIS variant.

第 9 轮测试目前是最新的(2014 年 5 月)。测试了许多 IIS 风格,但 aspnet-stripped 似乎是最快的 IIS 变体。

Here are the results in responses per second(higher is better):

以下是每秒响应的结果(越高越好):

  • JSON Serialization
    • nodejs: 228,887
    • aspnet-stripped: 105,272
  • Single Query
    • nodejs-mysql: 88,597
    • aspnet-stripped-raw: 47,066
  • Multiple Queries
    • nodejs-mysql: 8,878
    • aspnet-stripped-raw: 3,915
  • Plain Text
    • nodejs: 289,578
    • aspnet-stripped: 109,136
  • JSON 序列化
    • 节点: 228,887
    • aspnet 剥离: 105,272
  • 单一查询
    • nodejs-mysql: 88,597
    • aspnet剥离原始: 47,066
  • 多个查询
    • nodejs-mysql: 8,878
    • aspnet剥离原始: 3,915
  • 纯文本
    • 节点: 289,578
    • aspnet 剥离: 109,136

In all cases, Node.js tends to be 2x+ faster than IIS.

在所有情况下,Node.js 往往比 IIS 快 2 倍以上。

回答by Number 9

I have to agree with Marcus Granstrom the scenario is very important here.

我必须同意 Marcus Granstrom 的观点,这里的场景非常重要。

To be honest it sounds like you're making a high impact architectural decision. My advice would be to isolate the areas of concern and do a "bake off" between whatever stacks you are considering.

老实说,这听起来像是您正在做出一个影响很大的架构决策。我的建议是隔离关注的领域,并在您正在考虑的任何堆栈之间进行“烘烤”。

At the end of the day you are responsible for the decision and I don't think the excuse "Some guy on Stackoverflow showed me an article that said it would be fine" Will cut it with your boss.

归根结底,你要为这个决定负责,我不认为“Stackoverflow 上的某个人给我看了一篇文章说这很好”的借口会与你的老板断绝关系。

回答by Ondrej Rozinek

Main difference what I see is that node .js is dynamic programming language (type checking), so the types must be at run-time derived. The strongly typed languages like C# .NET has theoretically much more potential wins the fight against Node .js (and PHP etc.), especially where is expensive calculation. By the way the .NET should have better native interoperation with C/C++ than node .js.

我看到的主要区别是 node .js 是动态编程语言(类型检查),因此类型必须在运行时派生。像 C# .NET 这样的强类型语言理论上更有潜力战胜 Node .js(和 PHP 等),尤其是在计算成本高的地方。顺便说一下,与 node .js 相比,.NET 与 C/C++ 的本机互操作应该更好。