[Research] Spring boot vs node js - CPU Bound 성능 비교

gimseonjin616·2022년 4월 2일
0

Research

목록 보기
6/8

들어가며


요즘 node js에 대해 공부하고 있다. 관련해서 검색해보면 "Node js는 Non-Blocking I/O 작업에 특화되어 있으며 CPU 작업에 취약하다" 라는 내용이 많이 나온다.

따라서 이번에는 Spring boot와 Node js로 각각 CPU Bound Application & I/O Bound Application을 만들어서 비교해볼 것이다.

참고로 Node js는 프로그래밍 언어이기 때문에 Nest js 프레임워크를 사용할 것이다.

Spring boot vs Node js : 2021년 트렌드


구글 트렌드에 따르면 Spring boot와 비교했을 때 Node js가 더 많이 검색된 것을 볼 수 있다. 확실히 node js가 현재 트렌드인 듯 하다.

Spring boot vs Node js : CPU Bound Application


CPU Bound Application은 CPU 사용량이 많은 어플리케이션이다. 따라서 다음 로직을 수행하는 서버를 구현할 것이다.

1 ~ 10000까지 수를 모두 펙토리얼한 값을 더한다.

로직 수행은 모두 Service 로직에서 수행할 것이다.

Spring boot

CPU Controller

@RestController
public class CpuController {

    @Autowired
    private CpuService cpuService;

    @GetMapping("/")
    public Long cpubound(){
        return cpuService.getNumber();
    }
}

CPU Service

@Service
public class CpuService {
    public Long getNumber(){
        Long number = 0l;
        for(int i = 0; i <= 10000; i++){
            for(int j = 0; j<=i; j++){
                number = number + j;
            }
        }
        return number;
    }
}

Node js(with Nest js)

CPU Controller

@Controller('cpu')
export class CpuController {
  constructor(private readonly cpuService: CpuService) {}

  @Get()
  getNumber(): number{
    return this.cpuService.getNumber();
  }
}

CPU Service

@Injectable()
export class CpuService {
    getNumber() : number{
        var n : number = 0;
        for(var i = 0; i <= 10000; i++){
            for(var j = 0; j<=i; j++){
                n = n + j;
            }
        }
        return n;
    }
}

Artillery를 활용한 비교


비교 환경은 별도의 EC2 서버로 배포하지 않고 로컬환경에서 비교해볼 것이다.

Artillery Script는 아래와 같으며 로컬 환경이기 때문에 성공 여부만 볼 것이다.

timeout 설정을 줬기 때문에 CPU 처리 성능에 따라 성공 여부가 갈릴 것이다.

config:
  target: "http://localhost:8080"
  phases:
    - duration: 60
      arrivalRate: 5
  http:
    # Responses have to be sent within 10 seconds, or an `ETIMEDOUT` error gets raised.
    timeout: 100
scenarios:
  - flow:
      - get:
          url: "/"

Spring boot report

Node js

결론


로컬 환경에서 Node js, Spring boot 각각에서 CPU Bound Application을 돌려보니 예상과 다르게 Node js가 더 좋은 성능을 보였다.

TimeOut 설정을 100초로 줬기 때문에 Node js는 300개의 요청 중 16개의 요청을 100초 내에 처리한 것이고 Spring boot는 300개의 요청 중 단 한개도 100초내에 처리하지 못했다는 것을 확인할 수 있다.

그렇다면 Why???(나의 원인 추론)

-> Spring boot(java)는 요청이 들어오면 스레드가 생성이 된다. 즉 요청 한 개당 스레드 하나가 만들어진다! 위 상황에서는 CPU 작업이 처리되지 않았는데 요청이 계속 들어와 스레드가 계속 생성이 되어 오히려 성능이 떨어진 것으로 추측된다.

따라서 단일 요청에 CPU 사용량이 더 많은 케이스로 테스트해보면 결과가 달라질 수 있을 듯하다.
Artillery로 테스트 하는 게 아니라 Start_time - End_time 방식으로 1 ~ 100000 까지 아니라 1 ~ 1000000까지의 펙토리얼한 합을 구하는 경우로 테스트 해보면 다를 듯 하다.

profile
to be data engineer

1개의 댓글

comment-user-thumbnail
2023년 8월 14일

https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.server.server.tomcat.threads.max
스프링부트는 쓰레드풀에 기본 200개를 깔아놓고 시작하네요 👀 한정된 코어수에 여러 쓰레드가 돌게 되니 context-switch가 과도하게 일어나서 그런 게 아닐까 예상해봅니다. 노드는 쓰레드 하나가 요청들을 쌓아놓고 천천히 처리하는 방식이구요.

답글 달기