nodejs 다 중 스 레 드, 진정한 비 차단 (회전)

6010 단어
node 는 그 가 출시 한 후부 터 지금까지 칭찬 과 비난 을 받 은 것 은 모두 단일 스 레 드 모델 이다. 모든 임 무 는 한 스 레 드 에서 완성 되 었 다 (I / O 등 예외). 장점 은 스 레 드 를 자주 전환 하 는 비용 과 자원 을 서로 빼 앗 는 문제 등 을 면 하 는 것 이다. 그러나 nodejs 가 cpu 밀집 형 모델 에 직면 했 을 때 힘 이 부 쳤 다.비록 node 는 비동기 체 제 를 가지 고 있 지만 시간 소모 알고리즘 을 eventloop 에 버 리 고 다음 이벤트 순환 을 기다 리 고 할 수 있 습 니 다. 그러나 이것 은 단일 스 레 드 모델 이기 때문에 결국은 막 힐 수 있 습 니 다.
먼저 두 명사, Fibers 와 Threads 를 설명 하 세 요.Fibers 는 섬유 과정 이 라 고도 부 르 며 협동 프로그램 으로 이해 할 수 있 으 며, py 와 lua 와 같은 모델 이 있다.Fibers 를 사용 하면 자원 을 서로 빼 앗 는 것 을 피 할 수 있 고 cpu 와 메모리 의 소 모 를 줄 일 수 있 습 니 다. 그러나 Fibers 는 진정 으로 병행 할 수 없습니다. 같은 시간 에 하나의 Fibers 만 실 행 됩 니 다. 만약 에 그 중의 한 Fibers 에서 너무 많은 cpu 작업 을 하거나 순환 을 썼 다 면 전체 메 인 프로그램 이 걸 려 죽 을 것 입 니 다.node 의 비동기 이벤트 순환 모델 은 이것 과 비슷 합 니 다.
Threads 는 스 레 드 라 고도 부 릅 니 다. 그 는 같은 시간 에 실행 할 수 있 습 니 다. 그들 은 메 인 프로 세 스 의 메모 리 를 공유 합 니 다. 그 중 어느 순간 에 threads 가 잠 겨 서 메 인 스 레 드 와 다른 스 레 드 의 실행 에 영향 을 주지 않 습 니 다.그러나 이 모델 을 실현 하기 위해 서 는 더 많은 메모리 와 cpu 를 스 레 드 로 전환 하 는 비용 을 소모 해 야 합 니 다. 또한 여러 스 레 드 가 같은 메모리 셀 을 읽 고 쓸 수 있어 서 프로그램 이 무 너 질 수도 있 습 니 다.
node 가 다 중 스 레 드 를 지원 하 는 많은 방법 은 c / c + + 의 addon 을 사용 하여 이 루어 집 니 다. cpu 밀집 형 계산 이 필요 한 곳 에서 js 코드 를 c / c + 코드 로 바 꾸 는 것 입 니 다. 그러나 개발 자가 c + + 에 대해 잘 알 지 못 하면 개발 효율 이 많이 떨 어 집 니 다. 둘째, bug 도 쉽게 나 옵 니 다. 또한 addon 에 있 는 c + 코드 는 컴 파일 오류 외 에 디 버 깅 하기 어렵 다 는 것 을 알 고 있 습 니 다.vs 디 버 깅 c + 코드 가 편리 하지 않 기 때 문 입 니 다.
고무 적 인 소식, 우 리 는 왜 node 도 다 중 스 레 드 모델 을 지원 하지 못 하 게 합 니까?그래서 Jorge 는 node 가 다 중 스 레 드 모델 을 지원 하 는 모듈 을 개 발 했 습 니 다: threadsa_gogogithub 주소:https://github.com/xk/node-threads-a-gogo
threads - a - gogo (이하 TAGG 로 약칭) 라 는 모듈 이 있 으 면 우 리 는 node 에 게 더 많은 일 을 시 킬 수 있 습 니 다. 예전 에 저 는 node 가 i / o 밀집 형 장면 에 만 대응 할 수 있다 고 말 한 글 을 본 적 이 있 습 니 다. cpu 밀집 형 장면 은 apache 에 완 패 될 것 입 니 다. apache 는 모든 스 레 드 를 구 하 는 것 이기 때 문 입 니 다.그래서 cpu 밀집 형 임 무 를 처리 할 때 한 라인 의 고강도 계산 은 다른 라인 에 큰 영향 을 주지 않 는 다. 이와 유사 한 것 은 php 의 fastcgi 도 있다. 이것 은 node 와 php 를 비교 할 때 php 의 옹호자 들 이 줄곧 제기 한 이론 이다.
먼저 간단 한 테스트 를 해 보 겠 습 니 다. 우리 suqian 이 가장 좋아 하 는 피 보 나치 배열 로 보 겠 습 니 다. 다 중 스 레 드 를 넣 은 node 가 얼마나 강 한 지 보 겠 습 니 다.
    function fibo (n) {
      return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;
    }
    var n=8
    function back(){
        if(!--n) return console.timeEnd('no thread');
    }
    console.time('no thread');

    process.nextTick(function(){
        console.log(fibo (40));
        back();
    })
    process.nextTick(function(){
        console.log(fibo (40));
        back();
    })
    process.nextTick(function(){
        console.log(fibo (40));
        back();
    })
    process.nextTick(function(){
        console.log(fibo (40));
        back();
    })

    process.nextTick(function(){
        console.log(fibo (40));
        back();
    })process.nextTick(function(){
    console.log(fibo (40));
    back();})process.nextTick(function(){
    console.log(fibo (40));
    back();})process.nextTick(function(){
    console.log(fibo (40));
    back();})

우 리 는 8 개의 비동기 행 위 를 모 의 했 습 니 다. 테스트 용 node v 0.8.16 버 전 이기 때문에 process. nextTick 은 비동기 방법 입 니 다.마지막 으로 우리 의 출력 결 과 는:
165580141165580141165580141165580141165580141165580141165580141165580141no thread: 23346ms

다음 에 우 리 는 TAGG 모듈 을 사용 하여 똑 같은 8 번 의 피 보 나치 배열 계산 을 테스트 하고 성적 이 어떤 지 볼 까요?
function fibo (n) {
  return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;}console.time('8 thread');var numThreads= 8; //     ,    8var threadPool= require('threads_a_gogo').createPool(numThreads).all.eval(fibo); //        var i=8;var cb = function(err,data){ //             
    console.log(data);
    if(!--i){
        threadPool.destroy();
        console.timeEnd('8 thread');
    }}threadPool.any.eval('fibo(40)', cb); //         fibo(40)    threadPool.any.eval('fibo(40)', cb);threadPool.any.eval('fibo(40)', cb);threadPool.any.eval('fibo(40)', cb);threadPool.any.eval('fibo(40)', cb);threadPool.any.eval('fibo(40)', cb);threadPool.any.eval('fibo(40)', cb);threadPool.any.eval('fibo(40)', cb);

가장 무 거 운 결과:
1655801411655801411655801411655801411655801411655801411655801411655801418 thread: 9510ms

다 중 스 레 드 모델 을 사용 하지 않 는 node 에 비해 TAGG 모듈 을 사용 한 후, 우 리 는 4CPU 서버 에서 의 테스트 결과 가 두 배 이상 빨 라 졌 다.여기까지 우 리 는 CPU 밀집 형 임무 에 대응 하 는 비교적 완벽 한 해결 방안 을 찾 은 것 처럼 보 였 다. 그러나 어떤 동창 회 에 서 는 내 가 cluster 를 사용 하여 같은 일 을 할 수 있다 고 말 할 수 있다. 다음은 cluster 를 사용 하여 이 임 무 를 계산 하 는 상황 을 해 보 자.
var cluster = require('cluster');var numCPUs = 8;function fibo (n) {
  return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;}console.time('8 cluster');if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
  var i = 8;
  cluster.on('exit', function(worker, code, signal) {
        if(!--i){
            console.timeEnd('8 cluster');
            process.exit(0);
        }
  });} else {
    console.log(fibo (40));
    process.exit(0);}

코드 의 복잡 도 는 TAGG 를 사용 하 는 것 보다 훨씬 높 으 며, 피 보 나치 배열 을 동적 으로 계산 한 결과 라면 인 코딩 이 더욱 어렵 고, fork 에 서로 다른 인 자 를 걸 어야 하 며, 오류 가 발생 할 확률 도 높다.또한 더 중요 한 것 은 http 서버 를 만 드 는 것 이 라면 4 개의 cluster 가 fibo 를 계산 하고 있다 면 5 번 째 요청 node 는 처리 할 수 없고 TAGG 로 정상적으로 처리 할 수 있 기 때문에 cluster 는 단일 스 레 드 모델 의 cpu 밀집 계산 으로 인 한 차단 문 제 를 해결 할 수 없습니다. 테스트 결 과 를 살 펴 보 겠 습 니 다.
1655801411655801411655801411655801411655801411655801411655801411655801418 cluster: 11925ms

TAGG 모듈 에는 이벤트 트리거, 부 드 러 운 종료, 스 레 드 작업 상태 확인 등 더 많은 기능 이 있 습 니 다. 한 마디 로 TAGG 모듈 은 node 에 새로운 활력 을 불 어 넣 어 node 가 지적 해 온 cpu 밀집 작업 문 제 를 잘 해결 할 수 있 습 니 다. c + 코드 를 잘 하지 못 하 더 라 도 다 중 스 레 드 의 진정한 비 차단 node 프로그램 을 쉽게 작성 할 수 있 습 니 다.
원본 링크:http://cnodejs.org/topic/518b679763e9f8a5424406e9
마지막 으로 건어물 글 을 공유 합 니 다. 아주 멋 진 블 로그: Fibers and Threads in node. js – what for?
tagg 2, nodejs 다 중 스 레 드 모듈, 더 좋 은 api, nodejs 원생 모듈 지원, 크로스 플랫폼 지원, windows, Liux 와 mac 크로스 플랫폼 모듈 tagg 2, node 다 중 스 레 드 지원

좋은 웹페이지 즐겨찾기