Node.js与.Net性能

我已经读了很多关于Node.js快速并且能够容纳大量负载的内容。 有没有人有任何真实世界的证据证明这个vs其他框架,尤其是.Net? 我读过的大部分文章都是轶事,或者没有与.Net进行比较。

谢谢


快速处理大量LOAD是两件不同的事情。 如果每秒发送500个请求(在LOAD下),那么每秒处理一个请求时服务器速度真

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

我猜你正在寻找ASP.NET和节点之间的比较。 在这场战斗中,在编译/解释所有内容之后,你的表现可能会非常接近。 也许.NET是一个一点或许节点的一点,但它可能接近,以至于你不在乎。 我敢打赌.NET,但我不确定。

节点真正引人注目的地方是处理LOAD 。 这是技术真正不同的地方。 ASP.NET为其线程池中的每个请求分配一个线程,一旦ASP.NET耗尽了所有可用的线程,请求就开始排队。 如果您正在为@shankar提供的示例服务“Hello World”应用程序,那么这可能无关紧要,因为线程不会被阻止,并且您将能够处理大量请求用尽线程。 当您开始制作阻塞线程的I / O请求(调用数据库,向服务发出http请求,从磁盘读取文件)时,ASP.NET模型的问题就出现了。 这些阻塞请求意味着来自线程池的宝贵线程无所事事。 您拥有的阻止越多,您的ASP.NET应用程序将能够提供的LOAD越少。

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

问题在于ASP.NET(和.NET Framework)被创建为对异步I / O不加评论。 如果您编写同步代码或异步代码,.NET并不关心,所以决定是由开发人员决定。 部分原因是因为使用异步操作的线程和编程被认为是“困难的”,而.NET希望让每个人都感到高兴(noobs和专家)。 它变得更加困难,因为.NET最终以3-4种不同的模式来完成异步。 .NET 4.5正在试图回顾和改进.NET框架,以便围绕异步IO建立一个自发的模型,但是在您关心的框架实际上支持它之前可能需要一段时间。

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

再次,我没有任何硬性数据来证明这种或那种方式,但我认为节点将赢得典型Web应用程序的LOAD竞争。 一个高度优化的(100%异步).NET应用程序可能会让等效的node.js应用程序运行起来,但如果将所有.NET和所有节点应用程序的平均值都计算在内,平均节点可能会处理更多加载。

希望有所帮助。


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

我的硬件:戴尔Latitude E6510,酷睿i5(双核),8 GB内存,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上)。 这是一个非常基本的测试,决不是定论。 但我相信这是一个很好的起点。 在其他平台上,Nodejs在其他Web服务器上可能会更快,但在Windows上,IIS是胜利者。 希望将他们的ASP.NET MVC转换为nodejs的开发人员应该在继续之前暂停并思考两次。

更新(5/17/2012)Tomcat(在Windows上)似乎击败了IIS手,比静态html大约快3倍。

tomcat的

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

更新后的结论:我多次运行基准测试程序。 在WINDOWS上,Tomcat似乎是最快速的静态HTML服务器。

已更新(5/18/2012)以前,我有100,000个并发请求的总请求。 我将其增加到100万个请求和100,000个并发请求。 IIS以尖叫的胜利者身份出现,而Nodejs整理得最差。 我对以下结果进行了表述:

NodeJS vs IIS与Tomcat在WINDOWS上提供STATIC HTML


我必须同意马库斯·格兰斯特罗姆的说法,这里的情况非常重要。

说实话,这听起来像是你正在制定一个高影响的架构决策。 我的建议是隔离所关注的区域,并在你正在考虑的任何堆栈之间进行“烘烤”。

在这一天结束的时候,你要对这个决定负责,我不认为这个借口“Stackoverflow上的一些人向我展示了一篇文章,表示它会好起来的”会和你的老板一起削减它。

链接地址: http://www.djcxy.com/p/1505.html

上一篇: Node.js vs .Net performance

下一篇: Javascript: closures? eventlistener won't add