Node.js与.Net的性能比较

uelo1irk  于 2022-12-27  发布在  .NET
关注(0)|答案(5)|浏览(477)

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

tvz2xvvm

tvz2xvvm1#

FAST和处理大量的LOAD是两件不同的事情。一个真正FAST的服务器在每秒处理一个请求时,如果你每秒向它发送500个请求(在LOAD下),它可能会完全崩溃。

你还必须考虑静态(和缓存)与动态页面的比较。如果你担心静态页面,那么IIS可能会击败节点,因为IIS使用内核模式缓存,这意味着请求静态页面的请求甚至不会离开内核。
我猜你正在寻找ASP.NET和node之间的比较。在这场战斗中,在所有的东西都被编译/解释之后,你可能会在性能上非常接近。也许.NET有点,也许node有点,但它们可能足够接近,以至于你不在乎。我打赌是.NET,但我不确定。
这个节点真正吸引人的地方是处理LOAD。这是技术真正不同的地方。ASP.NET为线程池中的每个请求指定一个线程,一旦ASP.NET耗尽了所有可用的线程,请求开始排队。如果你正在服务“Hello World”应用程序,比如@shankar的例子,那么这可能就不那么重要了,因为线程不会被阻塞,而且在线程用完之前,您将能够处理大量的请求。ASP.NET模型的问题出现在您开始发出阻塞线程的I/O请求时(调用DB,向服务发出HTTP请求,从磁盘读取文件)。这些阻塞请求意味着线程池中有价值的线程什么也不做。阻塞越多,ASP.NET应用程序能够提供的LOAD就越少。
为了防止这种阻塞,您可以使用I/O完成端口,它在您等待响应时不需要占用线程。ASP.NET支持这一点,但不幸的是,.NET中的许多常见框架/库不支持。例如,ADO .NET支持I/O完成端口,但Entity Framework不使用它们。因此,您可以构建纯异步的ASP.NET应用程序,并处理大量负载。但是大多数人不这样做,因为它不像构建一个同步的那样容易,而且如果你这样做了,你可能无法使用框架中你最喜欢的一些部分(比如链接到实体)。
问题是ASP.NET(和.NET框架)都是为了对异步I/O不持意见而创建的。.NET并不关心您编写的是同步代码还是异步代码,因此这要由开发人员来决定。部分原因是线程化和使用异步操作编程被认为是“困难的”,.NET想让每个人都开心(新手和Maven)。这变得更加困难,因为.NET最终有3-4种不同的异步模式。.NET 4. 5正试图回到过去,改进.NET框架,以围绕异步IO建立一个固执己见的模型,但可能还需要一段时间,直到您关心的框架真正支持它。
另一方面,节点的设计者做出了一个武断的选择,即所有I/O都应该是异步的。由于这个决定,节点设计者还能够做出这样的决定:节点的每个示例都将是单线程的,以最小化线程切换,并且一个线程将只执行已经排队的代码。这可能是一个新请求,也可能是来自DB请求的回调,它可能是来自您所做的httprest请求的回调。节点试图通过消除线程上下文切换来最大化CPU效率。由于节点做出了所有I/O都是异步的这一固执己见的选择,这也意味着它的所有框架/插件都支持这种选择,在节点中编写100%异步的应用程序会更容易(因为node强制你编写异步的应用程序)。
同样,我没有任何确切的数字来证明这一点,但我认为node将赢得典型web应用的LOAD竞争。高度优化(100%异步)的.NET应用可能会给予等效的node.js应用物有所值,但如果你取所有.NET和所有node应用的平均值,平均而言node可能会处理更多的LOAD。

ubof19bj

ubof19bj2#

我在nodejs和IIS之间做了一个基本的性能测试。当发出"hello,world!"时,IIS比nodejs快大约2. 5倍。代码如下。
我的硬件:Dell Latitude E6510,酷睿i5(双核),8 GB RAM,Windows 7企业版64位操作系统
节点服务器

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

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

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

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);
        }
    }

}
}

结果:

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

结论:IIS比nodejs快大约2.5倍(在Windows上)。2这是一个非常初步的测试,并不意味着结论。3但我相信这是一个很好的起点。4 nodejs在其他Web服务器、其他平台上可能更快,但在Windows上IIS是赢家。5希望将ASP.NET MVC转换为nodejs的开发人员在继续之前应该停下来三思而后行。
更新(5/17/2012)Tomcat(在Windows上)似乎击败了IIS,在发布静态html方面比IIS快了大约3倍。
雄猫

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

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

更新结论:我运行了多次基准程序。Tomcat似乎是在windows上发布静态HTML最快的服务器。
更新(5/18/2012)以前我有100,000个总请求和10,000个并发请求。我将其增加到1,000,000个总请求和100,000个并发请求。IIS脱颖而出,Nodejs表现最差。我将结果列表如下:


l7mqbcuq

l7mqbcuq3#

NIO服务器(Node.js等)往往比BIO服务器(IIS等)更快。为了支持我的说法,TechEmpower是一家专门研究web framework benchmarks的公司。他们非常开放,有一个测试所有框架的标准方法。
第9轮测试是目前最新的(2014年5月)。有许多IIS风格的测试,但aspnet-stripped似乎是最快的IIS变体。
以下是以每秒响应为单位的结果(越高越好):

  • JSON序列化
  • 节点j:228,887
  • aspnet剥离:105,272
  • 单一查询
  • 节点-MySQL:88,597
  • aspnet剥离的原始数据:47,066
  • 多个查询
  • 节点-MySQL:8,878
  • aspnet剥离的原始数据:3,915
  • 纯文本
  • 节点j:289,578
  • aspnet剥离:109,136

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

kr98yfug

kr98yfug4#

我不得不同意马库斯·格兰斯特罗姆的观点,这一点非常重要。
老实说,这听起来像是你正在做一个影响力很大的架构决策,我的建议是隔离关注的领域,并在你正在考虑的任何堆栈之间进行“烘烤”。
在一天结束的时候,你要对这个决定负责,我不认为“Stackoverflow上的某个家伙给我看了一篇文章,说这会很好”的借口会让你的老板失望。

ie3xauqp

ie3xauqp5#

我看到的主要区别是node .js是动态编程语言(类型检查),所以类型必须在运行时派生。像C# .NET这样的强类型语言在理论上有更大的潜力赢得与Node .js(和PHP等)的战斗,特别是在昂贵的计算。顺便说一下,.NET应该比node. js有更好的与C/C++的本地互操作。

相关问题