ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NodeJs 동기(블로킹)와 비동기(논블로킹) 분석 기록
    공부하기/node.js 2023. 5. 7. 17:49

    사전지식

    - 블로킹은 Node.js 프로세스에서 추가적인 JavaScript의 실행을 위해 JavaScript가 아닌 작업이 완료될 때까지 기다려야만 하는 상황입니다. 이는 이벤트 루프가 블로킹 작업을 하는 동안 JavaScript 실행을 계속할 수 없기 때문입니다.

     

    - Node.js 표준 라이브러리의 모든 I/O 메서드는 논블로킹인 비동기 방식을 제공하고 콜백 함수를 받습니다. 일부 메서드는 같은 작업을 하는 블로킹 메서드도 가지는데 이는 이름 마지막에 Sync가 붙습니다.


    테스트 환경

    - Mac M1 Pro

    - Node v18.13.0

    - VueJs

    - NestJs


    테스트 코드

     

    fe

    vue.js
    
    async mounted() {
        let testCount = 10;
        const httpRequest = async (idx) => {
          const label = idx.toString();
          console.time(label);
          // console.time("start");
          const { data } = await axios.get("http://localhost:3000/api/sync");
          console.timeEnd(label);
          // console.time("end");
          return data;
        };
        const requests = [];
        while (testCount > 0) {
          const req = httpRequest(testCount);
          requests.push(req);
          --testCount;
        }
        console.time("test");
        await Promise.all(requests);
        console.timeEnd("test");
      },

     

     

    be

    nestjs - middleWare
    
    import { Injectable, NestMiddleware } from '@nestjs/common';
    import { Request, Response, NextFunction } from 'express';
    import { Logger } from '@nestjs/common';
    
    const chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
    
    @Injectable()
    export class TimingMiddleware implements NestMiddleware {
      private readonly logger = new Logger('HTTP');
    
      use(req: Request, res: Response, next: NextFunction) {
        const shiftChar = chars.shift();
        const start = Date.now();
        res.on('finish', () => {
          const duration = Date.now() - start;
          this.logger.log(
            `${req.method} ${shiftChar} ${req.originalUrl} ${res.statusCode} ${duration}ms`,
          );
        });
        next();
      }
    }
    
    nestjs - controller
    
    import { Controller, Get } from '@nestjs/common';
    import * as fs from 'fs';
    
    @Controller()
    export class FileSyncController {
      constructor() {}
    
      @Get('sync')
      syncTest() {
      // 60만줄의 txt 파일
        const data = fs.readFileSync('src/file-sync/dummy.txt', 'utf8');
    
        return data;
      }
    
      @Get('async')
      asyncTest() {
        // 60만줄의 txt 파일
        const data = fs.readFile('src/file-sync/dummy.txt', 'utf8', (err, data) => {
          return data;
        });
        return data;
      }
    }

    테스트 결과

    동기 api 요청 결과

    총 7.1초 소요

    동기 요청 전 cpu

     

    동기 요청 후 cpu

     

    비동기 api 요청 결과

    총 0.02초 소요

    비동기 요청 전 cpu

    비동기 요청 후 cpu


    분석 결과

     

    동기

     

    -> 작업 시간 대략 7초

    -> 동기 방식은 순차적으로 작업을 진행하기 때문에 작업 속도가 매우 느리다.

    -> 프로세스가 실행중이면 존재하면 다른 프로세스는 대기해야한다.

    -> 프론트엔드 코드를 실행하면 순차적으로 응답이 리턴되는걸 확인할 수 있다. ( 동시성이 낮다 )

    -> 하나의 작업을 끝낼때까지 대기하므로 cpu 자원을 더 많이 소모한다.

     

    비동기

    -> 작업 시간 대략 0.02초

    -> 비동기 방식은 이벤트 루프와 백그라운드 자원을 활용하여 작업이 마치 동시에 진행되는 것처럼 보이는 효과를 얻을 수 있음

    -> 백그라운드 자원을 활용하기 때문에 단일 쓰레드이지만 병렬적으로 작업을 수행할 수 있음

    -> 병렬적으로 작업을 처리하기 때문에 스루풋이 동기 방식에 비해 높다.

    -> cpu 자원을 효율적으로 사용하기 때문에 cpu 점유율이 동기 방식에 비해 낮다.

    -> 프론트엔드 코드를 실행하면 거의 동시에 모든 요청과 응답을 확인할 수 있다. ( 동시성이 높다 )

    '공부하기 > node.js' 카테고리의 다른 글

    TypeOrm Migration 학습  (0) 2023.04.08
    NestJs, Redis 캐싱 기록  (0) 2023.03.12
    NestJs Cache 탐색 및 기록  (0) 2023.03.09
    NestJs Swagger 문서 만들기  (0) 2023.03.02
    헥사고날 NestJs, TypeOrm dto type 리펙토링  (0) 2023.02.26
Designed by Tistory.