안녕하세요 오랜만에 글을 쓰게 되는데요 

 

여기서는 궁금증을 다 풀어갈 예정입니다.

 

목적부터 말씀 드리면

 

A 함수

0.2초마다 A라는 배열을 채웁니다.

B 함수

0.2초마다 A라는 배열에 값이 차면 꺼내와서 테스트 플랫폼에 해당 내용으로 자동화를 요청합니다.

 

문제점

2개의 함수 모두 계속 loop을 돌면서 진행하게되는데 배열을 채우는 A함수는 지속적인 CPU I/O 가 발생하게 됩니다. 

Node.js에서는 기본적으로는 멀티스레드가 안되기 때문에 저번 포스팅에서 Piscina를 사용하는 예제를 보여드렸었습니다.

 

그래서 그에 대한 기본 샘플 파일을 작성 합니다.

 

Worker

'use strict'

// 테스트 용 
let memoryArray = [];

let worker ={
  today_resource_filtering,
  filtered_resource_request_automation
}
function today_resource_filtering(){
  return new Promise(async(resolve,reject)=>{
    try {
      
      let i=0;
      let closeCondition = 1000;
      while(true && i < closeCondition){
        console.warn(`today_resource_filtering : ${i}`);
        i++;
        // await wait(1000);
      }
      console.warn('Test Complete');

      resolve(true);
    } catch (error) {
      reject(error);
    }
  })
}
function filtered_resource_request_automation(){
  return new Promise(async(resolve,reject)=>{
    try {
      console.warn('Request Server Resource');


      let i=10;
      let closeCondition = 1000;
      while(true && i < closeCondition){
        console.warn(`resource_automation_request : ${i}`);
        i++;
      }
      console.warn('Test Complete');
      resolve(true);
      
    } catch (error) {
      reject(error);
    }
  })
}
// 테스트용 유틸 

function wait(time){
  return new Promise(async(resolve)=>{
    setTimeout(()=>{
      resolve(true);
    },time)
  })
}

module.exports = worker;

 

 

Using Piscina

const path = require('path');
const Piscina = require('piscina');

const piscina = new Piscina({
  filename:path.resolve(__dirname,'filter_and_request.js')
});

(async function(){
  const res = await Promise.all([
    piscina.run({},{name:"today_resource_filtering"}),
    piscina.run({},{name:"filtered_resource_request_automation"}),
  ]);

  console.warn(res);
})();

Not Using Piscina

let worker = require('./filter_and_request.js');




(async function(){
  const res = await Promise.all([
    worker.filtered_resource_request_automation(),
    worker.today_resource_filtering()
  ]);

  console.warn(res);
})();

 

Using Piscina 결과부터 보겠습니다.

 

엥? 멀티스레드라고 되어있었는데 한 작업이 끝나야 다른작업이 시작됩니다. 

 

기존의 worker의 내용을 바꿔보겠습니다.

 

function today_resource_filtering(){
  return new Promise(async(resolve,reject)=>{
    try {
      let i=0;
      let closeCondition = 1000000000;
      while(true && i < closeCondition){
        i++;
        // await wait(1000);
      }
      console.warn('Test Complete');

      resolve(i+'==today_resource_filtering');
    } catch (error) {
      reject(error);
    }
  })
}

closeCondition 값을 바꾸면서 반복을 하고 

 

(async function(){
  console.time('using_basic_js');
  const res = await Promise.all([
    piscina.run({},{name:"today_resource_filtering"}),
    piscina.run({},{name:"filtered_resource_request_automation"}),
  ]);
  console.warn(res);
  console.timeEnd('using_basic_js');
})();

각각의 실행자에서 이렇게 테스트해보겠습니다.

 

100000부터 0을 하나씩 추가하면 (워커가 2개니까 *2 하시면 될 것 같습니다.)

 

1. 1000000  (20만)     ( Piscina - 73ms   vs Node.js (Single Thread )  3ms )

오잉? 왜 피시나에서 더 걸리는거같죠? 

2. 10000000  ( 2000 만 ) ( Piscina - 74ms   vs Node.js (Single Thread )  13ms )

천만 정도 루프시 특이점이 노드는 10 ms 증가 피시나는 7 정도 증가 했습니다.

3. 100000000 ( 20억 ) ( Piscina - 545 ms   vs Node.js (Single Thread )  950ms )

둘의 차이가점점 좁혀집니다.

 

4. 10000000000 (200억) ( Piscina - 9002 ms   vs Node.js (Single Thread )  17767ms )

100억번의 루프 -> 워커가 2개기 때문에 어찌보면 200억 인데

여기서부터 차이가 나기 시작합니다. ( Piscina의 진가가 발휘됩니다. )  

 

 

5. 마지막으로 (2000억 번 순환 ++시 ) ( Piscina - 1m 33s   vs Node.js (Single Thread )  3m 05ss )

점점 늘어날수록 차이가 벌어집니다. 2000억 순환시 3배의 가량이 차이가 발생하게 됩니다. 

-> 기존의 10만 100만정도는 piscina의 인스턴스를 생성하기 위한 기본 세팅값에서 들어가는 작업에 대한 시간으로 보입니다.

 

1차 정리 

Piscina는 기본 세팅 시 70ms 정도가 소요 된다.

Promise의 2개의 워커를 사용시 루프시간에 따라 다르지만  3배까지도 차이가 발생

 

 

바로 다음 포스팅에서는 최대워커 수만큼 호출시 와 지금 은 함수를 return new Promise로 해서 Promise.all 로 받았지만

사실 진짜 원하는건 멀티스레드아니였나 

A , B함수에서A가 계속 루프돌고 CPU 연산을 하면 B는 실행도 못하는게 실행되는게 아니였나? 라는 의문에 대한 해결을 위한 포스팅을 하겠습니다.

 

 

+ Recent posts