[.net] Node.js 및 .Net 성능

Node.js가 빠르며 많은 양의 부하를 수용 할 수있는 것에 대해 많이 읽었습니다. 누구 든지이 프레임 워크와 다른 프레임 워크, 특히 .Net에 대한 실제 증거가 있습니까? 내가 읽은 대부분의 기사는 일화이거나 .Net과 비교할 수 없습니다.

감사



답변

FAST 하고 많은 LOAD를 처리하는 것은 서로 다른 두 가지입니다. 초당 하나의 요청을 처리 할 때 실제로 빠른 서버는 초당 500 개의 요청을 보내는 경우 ( LOAD 아래 ) 완전히 손상 될 수 있습니다 .

또한 정적 페이지와 캐시 된 페이지와 동적 페이지를 고려해야합니다. 정적 페이지가 걱정된다면 IIS가 커널 모드 캐싱을 사용하기 때문에 IIS가 노드를 이길 수 있습니다. 이는 정적 페이지를 요청하는 요청이 커널을 벗어나지 않을 수도 있음을 의미합니다.

ASP.NET과 노드 사이의 비교를 찾고 있다고 생각합니다. 이 전투에서 모든 것이 컴파일 / 통역 된 후에는 성능이 거의 비슷할 것입니다. .NET이 FASTER 이거나 노드가 FASTER 일 수도 있지만 신경 쓰지 않을 정도로 가깝습니다. .NET에 베팅했지만 확실하지 않습니다.

노드가 실제로 매력적인 곳은 LOAD 를 처리하는 것 입니다. 이것은 기술이 실제로 다른 곳입니다. ASP.NET은 스레드 풀의 각 요청에 대한 스레드를 전용으로 지정하고 ASP.NET이 모두 사용 가능 해지면 사용 가능한 모든 스레드 요청이 큐잉되기 시작합니다. @shankar의 예제와 같은 “Hello World”앱을 제공하는 경우 스레드가 차단되지 않고 많은 요청을 처리 할 수 ​​있기 때문에 중요하지 않을 수 있습니다. 스레드가 부족합니다. ASP.NET 모델의 문제점은 스레드를 차단하는 I / O 요청 (DB 호출, 서비스에 대한 http 요청, 디스크에서 파일 읽기)을 시작할 때 발생합니다. 이러한 차단 요청은 스레드 풀의 소중한 스레드가 아무 작업도 수행하지 않음을 의미합니다. 차단이 많을수록ASP.NET 앱을 로드 할 수있게됩니다.

이러한 블로킹을 방지하려면 응답을 기다리는 동안 스레드를 유지할 필요가없는 I / O 완료 포트를 사용하십시오. ASP.NET은 이것을 지원하지만 불행히도 .NET DO N’T의 많은 공통 프레임 워크 / 라이브러리를 지원합니다. 예를 들어 ADO.NET은 I / O 완료 포트를 지원하지만 Entity Framework는 해당 포트를 사용하지 않습니다. 따라서 순수하게 비동기적이고 많은 부하를 처리하는 ASP.NET 응용 프로그램을 만들 수 있지만 대부분의 사람들은 동기식 응용 프로그램을 만드는 것만 큼 쉽지 않으므로 좋아하는 부분을 사용하지 못할 수도 있습니다. 당신이하는 경우 프레임 워크 (예 : linq to entity).

문제는 ASP.NET (및 .NET Framework)이 비동기 I / O에 대해 의견이 맞지 않도록 만들어 졌다는 것입니다. .NET은 동기식 코드 나 비동기식 코드를 작성하더라도 신경 쓰지 않으므로이 결정을 내리는 것은 개발자의 책임입니다. 비동기 작업을 통한 스레딩 및 프로그래밍이 “고난”한 것으로 생각되어 .NET이 모든 사람을 행복하게 만들려고했기 때문입니다 (누브 및 전문가). .NET이 비동기를 수행하기 위해 3-4 가지 패턴으로 끝나기 때문에 훨씬 어려워졌습니다. .NET 4.5는 돌아가서 .NET 프레임 워크를 개조하여 비동기 IO에 대한 의견이있는 모델을 만들려고하지만 관심있는 프레임 워크가 실제로이를 지원할 때까지는 시간이 걸릴 수 있습니다.

반면 노드 디자이너는 모든 I / O가 비동기 적이어야한다고 의견을 내 렸습니다. 이 결정으로 인해 노드 설계자들은 또한 스레드 전환을 최소화하기 위해 각 노드 인스턴스가 단일 스레드가되고 하나의 스레드가 대기중인 코드 만 실행하도록 결정할 수있었습니다. 새로운 요청 일 수도 있고, DB 요청의 콜백 일 수도 있고, http 나머지 요청의 콜백 일 수도 있습니다. 노드는 스레드 컨텍스트 스위치를 제거하여 CPU 효율성을 최대화하려고합니다. 노드는 ALL I / O가 비동기식이라는이 의견을 선택했기 때문에 모든 프레임 워크 / 애드온이이 선택을 지원함을 의미합니다. 노드가 100 % 비동기 인 앱을 작성하는 것이 더 쉽습니다 (노드가 비동기 인 앱을 작성해야하기 때문에).

다시 말하지만, 어떤 식 으로든 증명할 수있는 어려운 숫자는 없지만 노드가 일반적인 웹 응용 프로그램의 LOAD 경쟁에서 이길 것이라고 생각합니다. 고도로 최적화 된 (100 % 비동기) .NET 앱은 동등한 node.js 앱에 돈을 줄 수 있지만 모든 .NET 및 모든 노드 앱의 평균을 가져간 경우 평균 노드에서 더 많은 것을 처리 할 수 ​​있습니다 하중.

희망이 도움이됩니다.


답변

nodejs와 IIS 사이에서 기본적인 성능 테스트를 수행했습니다. “hello, world!”를 제거 할 때 IIS는 nodejs보다 약 2.5 배 빠릅니다. 아래 코드.

내 하드웨어 : Dell Latitude E6510, Core i5 (이중 코어), 8GB RAM, Windows 7 Enterprise 64 비트 OS

노드 서버

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). 이것은 매우 기초적인 테스트이며 결코 결정적인 것은 아닙니다. 그러나 이것이 좋은 출발점이라고 생각합니다. Node.js는 다른 웹 서버, 다른 플랫폼에서 더 빠를 수 있지만 Windows IIS에서는 승자가됩니다. ASP.NET MVC를 nodejs로 변환하려는 개발자는 진행하기 전에 일시 중지하고 두 번 생각해야합니다.

업데이트 됨 (2012 년 5 월 17 일) Tomcat (Windows의 경우)은 정적 HTML을 제거 할 때 IIS보다 약 3 배 빠른 IIS 손을이기는 것으로 보입니다.

수코양이

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

바람둥이 결과

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을 처리하는 데 가장 빠른 서버 인 것으로 보입니다.

업데이트 됨 (2012 년 5 월 18 일) 이전에는 10,000 개의 동시 요청과 함께 총 10 만 건의 요청이있었습니다. 총 요청 1,000,000 건과 동시 요청 100,000 건으로 늘 렸습니다. IIS가 비명을 지르며 Nodejs가 최악의 결과를 냈습니다. 아래 결과를 표로 작성했습니다.

WINDOWS에서 정적 HTML을 제공하는 NodeJS와 IIS 및 Tomcat.


답변

NIO 서버 (Node.js 등)는 BIO 서버보다 빠른 경향이 있습니다. (IIS 등). 내 주장을 뒷받침하기 위해 TechEmpower는 웹 프레임 워크 벤치 마크 전문 회사입니다 . 그것들은 매우 개방적이며 모든 프레임 워크를 테스트하는 표준 방법을 가지고 있습니다.

라운드 9 테스트는 현재 최신입니다 (2014 년 5 월). 많은 IIS 버전이 테스트되었지만 aspnet-stripped는 가장 빠른 IIS 변형 인 것 같습니다.

초당 응답 의 결과는 다음과 같습니다 (높을수록 좋습니다).

  • JSON 직렬화
    • nodejs : 228,887
    • aspnet- 스트립 : 105,272
  • 단일 쿼리
    • nodejs-mysql : 88,597
    • ASPNET-STRIP-RAW : 47,066
  • 여러 개의 쿼리
    • nodejs-mysql : 8,878
    • ASPNET-STRIP-RAW : 3,915
  • 일반 텍스트
    • nodejs : 289,578
    • aspnet- 스트립 : 109,136

모든 경우에 Node.js는 IIS보다 2 배 이상 빠릅니다.


답변

나는 여기서 시나리오가 매우 중요하다는 Marcus Granstrom에 동의해야합니다.

솔직히 말해서 건축 결정을 내리는 것 같습니다. 내 조언은 관심 영역을 격리하고 고려중인 스택 사이에서 “제빵”하는 것입니다.

하루가 끝나면 결정에 대한 책임이 있으며 “Stackoverflow의 일부 사람이 나에게 괜찮다고 말한 기사를 보여주었습니다”라고 변명하지는 않습니다.


답변

내가 보는 주요 차이점은 node .js가 동적 프로그래밍 언어 (유형 검사)이므로 유형이 런타임에서 파생되어야한다는 것입니다. C # .NET과 같은 강력한 형식의 언어는 이론적으로 노드 .js (및 PHP 등)와의 싸움에서 이론적으로 훨씬 더 많은 잠재력을 가지고 있습니다. 그런데 .NET은 노드 .js보다 C / C ++와 더 나은 기본 상호 운용성을 가져야합니다.


답변