programing

Node.js가 내부적으로 스레드에 의존하고 있을 때 본질적으로 더 빠른 방법은 무엇입니까?

nicescript 2022. 9. 30. 13:22
반응형

Node.js가 내부적으로 스레드에 의존하고 있을 때 본질적으로 더 빠른 방법은 무엇입니까?

저는 방금 다음 비디오를 보았습니다.Node.js에 대한 소개입니다만, 아직 속도상의 이점을 얻을 수 있는 방법을 이해하지 못하고 있습니다.

주로 Ryan Dahl(Node.js의 작성자)은 Node.js가 스레드 베이스가 아닌 이벤트 루프 베이스라고 말합니다.스레드는 비용이 많이 들기 때문에 동시 프로그래밍 전문가에게만 맡겨야 합니다.

그런 다음 내부 스레드 풀을 가진 기반이 되는 C 구현을 가진 Node.js의 아키텍처 스택을 보여 줍니다.따라서 Node.js 개발자는 자신의 스레드를 시작하거나 스레드 풀을 직접 사용하지 않습니다.비동기 콜백을 사용합니다.그 정도는 이해해요.

Node.js가 아직 스레드를 사용하고 있다는 것은 이해할 수 없는 점입니다.실장을 숨기고 있을 뿐인데 50명의 사용자가 50개의 파일(현재 메모리에 없는 파일)을 요구하면 50개의 스레드가 필요하지 않습니까?

유일한 차이점은 Node.js 개발자는 내부적으로 관리되기 때문에 스레드화된 세부사항을 코드화할 필요가 없지만 기본적으로는 스레드를 사용하여 IO(차단) 파일 요청을 처리합니다.

즉, 실제로는 하나의 문제(스레딩)를 안고, 그 문제가 존재하는 동안 숨기고 있지 않습니까?주로 여러 스레드, 컨텍스트 스위칭, 데드록 등입니다.

내가 아직 이해하지 못하는 세부 사항이 있을 것이다.

여기에는 실제로 몇 가지 다른 것들이 결합되어 있습니다.하지만 실타래는 정말 힘들다는 밈에서 시작합니다.따라서 어려운 경우에는 스레드를 사용하여 1) 버그로 인한 파손과 2) 최대한 효율적으로 사용하지 않는 경우가 많습니다.(2) 질문의 대상이 됩니다.

그가 제시한 예 중 하나를 생각해 보십시오. 요청이 들어와 쿼리를 실행하고 그 결과를 바탕으로 작업을 수행합니다.표준적인 순서로 쓰면, 코드는 다음과 같이 됩니다.

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

그 동안 아무것도 .query()(Ryan에 따르면 Apache는 원래 요구를 만족시키기 위해 단일 스레드를 사용하는 반면 nginx는 그렇지 않기 때문에 그가 말한 경우보다 성능이 우수합니다.)

만약 당신이 정말 똑똑하다면, 쿼리를 실행하는 동안 환경이 중단되어 다른 작업을 수행할 수 있는 방법으로 위의 코드를 표현해야 합니다.

query( statement: "select smurfs from some_mushroom", callback: go_do_something_with_result() );

이것이 기본적으로 node.js가 하는 일입니다.언어나 환경 때문에 편리한 방법으로, 폐쇄에 관한 포인트 때문에, 무엇이 언제 실행되는지 환경이 잘 알 수 있도록 코드를 꾸미는 것입니다.이와 같이 node.js는 비동기 I/O를 발명했다는 점에서 새로운 것은 아니지만(누구도 이와 같은 주장을 하지 않았다) 표현 방식이 조금 다르다는 점에서 새로운 것입니다.

주의: 환경에서 실행 내용과 시기를 정확하게 파악할 수 있다고 하면, 특히 I/O를 시작할 때 사용한 스레드를 사용하여 다른 요청을 처리하거나 병렬로 수행할 수 있거나 다른 병렬 I/O를 시작할 수 있습니다(노드가 더 많은 작업을 시작할 수 있을 만큼 정교하지는 않습니다).같은 요청이지만, 이해하실 수 있습니다.)

참고! 이것은 오래된 대답입니다.대략적인 개요에서는 여전히 사실이지만, 지난 몇 년간 Node의 급속한 발전으로 인해 일부 세부 사항이 변경되었을 수 있습니다.

스레드를 사용하는 이유는 다음과 같습니다.

  1. open()O_NONBLOCK 옵션은 파일에서 작동하지 않습니다.
  2. 논블로킹 IO를 지원하지 않는 서드파티 라이브러리가 있습니다.

논블로킹 IO를 위조하려면 스레드가 필요합니다.다른 스레드에서 블로킹 IO를 수행합니다.그것은 추악한 해결책이며 많은 오버헤드를 초래한다.

하드웨어 레벨에서는 더 나빠집니다.

  • DMA를 사용하면 CPU는 IO를 비동기적으로 오프로드합니다.
  • 데이터는 IO 디바이스와 메모리 간에 직접 전송됩니다.
  • 커널은 이를 동기식 블로킹시스템 콜로 랩합니다.
  • Node.js는 블로킹시스템 콜을 스레드로 랩합니다.

이건 그냥 멍청하고 비효율적이야.그래도 되네!Node.js는 이벤트 중심의 비동기 아키텍처 뒤에 추악하고 번거로운 디테일이 숨겨져 있기 때문에 즐길 수 있습니다.

향후 파일용으로 O_NONBLOCK을 실장하는 사람이 있을까요?...

편집: 친구와 상의한 결과, 스레드 대신 폴링이 있다고 합니다: 타임아웃을 0으로 지정하고 반환된 파일 기술자에 대해 IO를 수행합니다(차단되지 않음을 보증합니다).

제가 여기서 "잘못한 일"을 하고 있는 것 같아서, 만약 그렇다면 저를 삭제하고 사과드립니다.특히, 저는 어떤 사람들이 만든 깔끔하고 작은 주석을 어떻게 만드는지 모르겠습니다.다만, 이 스레드에 대해 많은 우려/관찰이 있습니다.

1) 인기 있는 답변 중 하나에서 의사 코드의 코멘트 요소

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

본질적으로 가짜입니다.만약 스레드가 컴퓨팅이라면, 그것은 빈둥거리는 것이 아니라, 필요한 일을 하고 있는 것입니다.한편 단순히 IO가 완료되기를 기다리고 있을 뿐 CPU 시간을 사용하지 않는 경우 커널 스레드 제어 인프라스트럭처의 요점은 CPU가 유용한 작업을 찾는 것입니다.여기서 제시한 바와 같이 '손가락 비틀기'를 하는 유일한 방법은 폴링 루프를 만드는 것입니다.실제 웹 서버를 코드화한 사람은 아무도 그렇게 할 수 없습니다.

2) "스레드는 어렵다" 데이터 공유의 맥락에서만 의미가 있습니다.독립된 웹 요청을 처리할 때처럼 기본적으로 독립된 스레드가 있는 경우 스레드는 매우 간단합니다.한 작업을 처리하는 방법의 선형 흐름을 코드화하고 여러 요청을 처리할 수 있다는 것을 알고 있으면 각 스레드가 효과적으로 독립적입니다.개인적으로 대부분의 프로그래머에게 클로즈/콜백 메커니즘을 배우는 것은 단순히 위에서 아래로 스레드 버전을 코드화하는 것보다 더 복잡하다고 생각합니다.(하지만 스레드 간에 통신해야 하는 경우 삶은 매우 빨리 진행되지만 클로즈/콜백 메커니즘이 실제로 변화한다는 것은 납득할 수 없습니다.에서는, 스레드에서도 이 어프로치를 실현할 수 있기 때문에, 옵션이 한정됩니다.어쨌든, 이것은 여기에서는 전혀 관계가 없는, 전혀 다른 논의입니다).

3) 지금까지 특정 유형의 콘텍스트스위치가 다른 어떤 유형의 콘텍스트스위치에 비해 시간이 많이 걸리는 이유에 대해서는 아무도 실제 증거를 제시하지 않았습니다.멀티태스킹 커널 작성 경험(임베디드 컨트롤러의 경우 소규모이지만 실제 OS만큼 화려한 것은 없다)을 통해 알 수 있습니다.

4) 지금까지 본 그림 중 Node가 다른 웹 서버보다 얼마나 빠른지 보여주는 것은 모두 심각한 결함이지만, Node에 대해 확실히 받아들일 수 있는 한 가지 이점을 간접적으로 보여주는 점에서 결함이 있습니다(그것은 결코 중요하지 않습니다).노드는 튜닝이 필요하지 않은 것 같습니다(실제로도 허용되지 않습니다).스레드 모델이 있는 경우 예상되는 부하를 처리할 수 있는 충분한 스레드를 작성해야 합니다.이렇게 하면 성적이 나빠져요.스레드가 너무 적으면 CPU는 아이돌 상태이지만 더 많은 요구를 받아들일 수 없고 너무 많은 스레드를 생성하면 커널 메모리가 낭비되고 Java 환경의 경우 메인 힙 메모리도 낭비됩니다.Java의 경우 효율적인 가비지 수집(현재는 G1에서 변경될 수 있지만 적어도 2013년 초 현재 JURI는 아직 남아 있는 것으로 보인다)이 많은 여분의 힙을 가지고 있는 것에 의존하기 때문에 힙을 낭비하는 것이 시스템 성능을 망치는 첫 번째 최선의 방법입니다.따라서 문제가 있습니다. 너무 적은 수의 스레드로 튜닝하면 CPU가 유휴 상태가 되고 스루풋이 저하되며 너무 많은 스레드로 튜닝하면 다른 방식으로 작동이 중단됩니다.

5) Node의 어프로치가 「설계상 고속」이라고 하는 주장의 논리를 받아들일 수 있는 다른 방법이 있습니다.그것은 바로 이것입니다.대부분의 스레드 모델에서는 보다 적절한(값 판단 경보:) 및 보다 효율적인(값 판단이 아닌) 프리엠프티브모델 위에 레이어된 타임슬라이스 컨텍스트스위치 모델을 사용합니다.이는 두 가지 이유로 발생합니다.첫 번째 이유는 대부분의 프로그래머가 우선 순위 프리엠프션을 이해하지 못하는 것 같습니다.두 번째 이유는 Windows 환경에서 스레드를 학습하면 타임슬라이싱이 좋든 싫든 상관없습니다(물론 이것은 첫 번째 포인트를 강화합니다.특히 Java의 첫 번째 버전은 Solaris 구현에서 우선 순위 프리엠프션을 사용했습니다.d Windows에서의 타임슬라이싱대부분의 프로그래머는 "Solaris에서는 스레딩이 작동하지 않는다"는 것을 이해하지 못하고 불만을 표시했기 때문에 모델을 모든 곳에서 timeslice로 변경했습니다.어쨌든 결론은 타임슬라이싱에 의해 컨텍스트스위치가 추가(및 잠재적으로 불필요한)가 생성된다는 것입니다.모든 콘텍스트스위치는 CPU에 시간이 걸리며, 그 시간은 실제 작업 시 수행할 수 있는 작업에서 효과적으로 제거됩니다.다만, 시차를 두고 콘텍스트 스위칭에 소비하는 시간은, 매우 이상한 일이 일어나지 않는 한, 전체 시간의 극히 일부만을 넘지 않는 것이 좋습니다.단, 심플한 웹 서버에서는 그렇게 될 것이라고 생각할 이유가 없습니다.따라서 타임슬라이싱에 관여하는 과도한 콘텍스트스위치는 비효율적이지만(또한 커널 스레드에서는 일반적으로 발생하지 않습니다), throughput의 몇 %가 차이가 납니다.이는 노드에 대해 종종 암시되는 퍼포먼스 클레임에 포함되는 정수 요인이 아닙니다.

Anyway, apologies for that all being long and rambly, but I really feel that so far, the discussion hasn't proved anything, and I would be pleased to hear from someone in either of these situations:

a) a real explanation of why Node should be better (beyond the two scenarios I've outlined above, the first of which (poor tuning) I believe is the real explanation for all the tests I've seen so far. ([edit], actually, the more I think about it, the more I'm wondering if the memory used by vast numbers of stacks might be significant here. The default stack sizes for modern threads tend to be pretty huge, but the memory allocated by a closure-based event system would be only what's needed)

b) a real benchmark that actually gives a fair chance to the threaded server of choice. At least that way, I'd have to stop believing that the claims are essentially false ;> ([edit] that's probably rather stronger than I intended, but I do feel that the explanations given for performance benefits are incomplete at best, and the benchmarks shown are unreasonable).

Cheers, Toby

What I don't understand is the point that Node.js still is using threads.

Ryan uses threads for that parts that are blocking(Most of node.js uses non-blocking IO) because some parts are insane hard to write non blocking. But I believe Ryan wish is to have everything non-blocking. On slide 63(internal design) you see Ryan uses libev(library that abstracts asynchronous event notification) for the non-blocking eventloop. Because of the event-loop node.js needs lesser threads which reduces context switching, memory consumption etc.

스레드는 다음과 같은 비동기 설비가 없는 함수를 처리하는 데만 사용됩니다.stat().

stat()함수는 항상 블로킹이기 때문에 node.display는 스레드를 사용하여 메인스레드(이벤트루프)를 블로킹하지 않고 실제 콜을 실행해야 합니다.이러한 함수를 호출할 필요가 없는 경우 스레드 풀의 스레드가 사용되지 않을 수 있습니다.

I know nothing about the internal workings of node.js, but I can see how using an event loop can outperform threaded I/O handling. Imagine a disc request, give me staticFile.x, make it 100 requests for that file. Each request normally takes up a thread retreiving that file, thats 100 threads.

첫 번째 요구가 퍼블리셔 오브젝트가 되는 스레드를 1개 작성한다고 가정합니다.다른 99개의 요구는 처음에 staticFile.x의 퍼블리셔 오브젝트가 있는지 여부를 확인합니다.그 경우 작업 중에 재생하고, 그렇지 않으면 새로운 스레드를 시작하여 새로운 퍼블리셔 오브젝트를 만듭니다.

단일 스레드가 완료되면 staticFile.x가 100명의 모든 리스너에 전달되고 그 자체가 파괴되므로 다음 요구는 새로운 스레드 및 퍼블리셔 개체를 만듭니다.

따라서 위의 예에서는 100개의 스레드와 1개의 스레드이지만 100개의 디스크 룩업이 아닌 1개의 디스크 룩업으로 얻을 수 있는 이득은 매우 큽니다.라이언은 똑똑한 사람이에요!

또 다른 시각은 영화 시작 부분에서 그가 보여준 사례 중 하나이다.대신:

pseudo code:
result = query('select * from ...');

데이터베이스에 대한 100개의 개별 쿼리와:

pseudo code:
query('select * from ...', function(result){
    // do stuff with result
});

쿼리가 이미 진행 중인 경우 다른 동등한 쿼리는 단순히 시류에 편승하기 때문에 단일 데이터베이스 라운드 트립으로 100개의 쿼리를 가질 수 있습니다.

Node.JS는 단일 스레드를 처리하는 블로킹 멀티 스레드 시스템에 비해 속도가 빠르지 않고(느리다는 의미도 아닙니다) 단일 스레드 처리 효율이 매우 높습니다.

나는 이 진술을 유추하여 설명하기 위해 도표를 만들었다.

enter image description here enter image description here

물론 블로킹 멀티 스레드 시스템(Node.js가 후드 아래에 있는 것과 동일) 위에 비블로킹 시스템을 구축할 수 있지만 매우 복잡합니다.그리고 차단되지 않는 코드가 필요한 곳이라면 언제든지 해야 합니다.

Javascript 에코시스템(nodejs 등)은 이를 구문으로 바로 사용할 수 있습니다.JS 언어 systanx는 필요한 모든 기능을 제공합니다.구문의 일부로서 코드의 판독자는 코드의 어디에 블록이 있는지, 어디에 비블록이 있는지를 즉시 알 수 있습니다.


멀티스레드 블로킹시스템의 블로킹 부분은 효율이 떨어집니다.차단된 스레드는 응답을 기다리는 동안 다른 용도로 사용할 수 없습니다.

논블로킹 싱글 스레드 시스템은 싱글 스레드 시스템을 최대한 활용합니다.

언급URL : https://stackoverflow.com/questions/3629784/how-is-node-js-inherently-faster-when-it-still-relies-on-threads-internally

반응형