JDK21 Virtual Thread 적용 비교

정원식·2023년 12월 16일

Virtual Thread 적용후 비교

결론

  • 아래 두가지 조건을 충족한다면 Platform Thread 를 사용하는것을 추천합니다.
    1. Tomcat 10.1.15 버전 이하
    2. 적절한 스레드 및 메모리 튜닝 적용

개요

  • JDK 21 에서 Virtual Thread 기능이 추가되면서 Spring Boot 3.1 에 각각의 스레드 타입을 적용후 비교해보았습니다~
    • JDK 19 에서 Preview Features 로 Virtual Thread 가 추가 되었습니다.
    • JDK 21 에서 Feature 로 적용되었습니다.
  • 이전 Spring Boot 2.6.15 버전에서 비교

배경지식: Platform Thread vs Virtual Thread

  • JVM 내부 스케줄링을 통해 제공되는 경량 스레드입니다.
  • 동작하는 동안, OS 에서 제공하는 스레드 (Platform Thread) 와 1대1로 매핑됩니다.
  • 블로킹 상황 발생시, 해당 Virtual Thread 는 블로킹 되고 다른 Virtual Thread 가 Platform Thread 에 연결되어 실행됩니다.
    • 이때, Platform Thread 가 변경되는게 아니므로 Context Switching 비용이 비교적 저렴합니다.
  • Platform Thread 대비 메모리를 적게 사용합니다.
    • Platfrom Thread: 약 2KB
    • Virtual Thrad: 200~300B
  • 따라서 Spring Web MVC 에서 Virtual Thread 적용시, 속도와 처리량이 올라갈것으로 예상됩니다.
  • 관련 자료

테스트에 사용한 버전

  • JDK: Termurin JDK 21.0.1+12
  • Spring Boot: 3.1.5
  • Spring Web MVC: 6.0.13
    • Tomcat 10.1.15
  • Spring Web Flux: 6.0.13

테스트

준비물

  • CentOS 7.9 환경 (NHN Cloud Instance)
  • 슈터
    • Gatling
  • 타겟
    • Spring WebMVC with Platform Thread (128MB Heap Memory)
      • 스레드풀에 1200 개의 스레드를 할당
    • Spring WebMVC with Virtual Thread (128MB Heap Memory)
    • Spring WebFlux (128MB Heap Memory)

인스턴스 세팅

1. 네트워크 관련 세팅

  • 요청량 만큼 포트(소켓=파일) 를 사용하기에 포트와 파일 용량을 늘려줍니다.
# /etc/sysctl.conf

# 포트 범위 증가
net.ipv4.ip_local_port_range = 1024 65535
# TIME_WAIT 인 포트를 사용할수 있도록 수정
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
  • Too Many Open Files 관련 아래 내용 추가 (한 프로세스가 동시에 열수 있는 최대 파일 갯수 증가)
# /etc/security/limits.conf

# 마지막 라인에 추가
* hard nofile 65535
* soft nofile 65535

2. 스레드 관련 세팅

  • Unable to create new native thread 관련 아래 내용 추가 (한 프로세스가 만들수 있는 최대 스레드 갯수 증가)
# /etc/security/limits.d/20-nproc.conf

# 마지막 라인에 추가
* hard nproc 65535
* soft nproc 65535

테스트 시나리오

  • 요청 처리 시나리오
    • DB, API 호출 등으로 인해 총 3초의 대기가 생겼다고 가정합니다.
    • 3초 동안 Thread.sleep 이후 응답
    • WebFlux 의 경우, Mono.delay 로 3초 대기후 응답
  • 부하 시나리오
    1. 처음 30초: 0 RPS 에서 Max RPS 까지 요청량을 높입니다.
    2. 후반 30초: Max RPS 에서 유지 합니다.

예상 결과

아래의 순서로 처리량이 높을것으로 예상했습니다..

  1. Spring WebFlux (128MB)
  2. Spring WebMVC with Virtual Thread (128MB)
  3. Spring WebMVC with System Thread (128MB)

테스트 결과

Max RPSPlatform ThreadVirtual ThreadWebFlux
100 RPS3002 ms3003 ms-
200 RPS3003 ms3004 ms-
300 RPS3006 ms3017.833 ms (6회 실행 평균)-
310 RPS3009 msjava.lang.OutOfMemoryError 발생-
320 RPS3014 msjava.lang.OutOfMemoryError 발생-
330 RPS3016.167 ms (6회 실행 평균)java.lang.OutOfMemoryError 발생-
340 RPSjava.lang.OutOfMemoryError 발생java.lang.OutOfMemoryError 발생-
350 RPSjava.lang.OutOfMemoryError 발생java.lang.OutOfMemoryError 발생-
...
400 RPSjava.lang.OutOfMemoryError 발생java.lang.OutOfMemoryError 발생-
...
1000 RPS--3014 ms
2000 RPS--3183 ms
3000 RPS--3216 ms
  • 예상과 다르게, Platform Thread 가 더 좋은 성능을 보여주었습니다 (약 10%)
  • Web Flux 는 약 10배 더 나은 성능을 보여주었습니다.
  • 아래 사항을 변경해서 테스트 해보았으나, 결과는 항상 Platform Thread 가 더 좋았습니다..
    • CPU 갯수 (1개, 2개)
    • 할당 힙메모리 (160MB)
    • Sleep 타임 변경 (0ms, 100ms, 1s)
    • 테스트툴 변경 (Apache Benchmark)
  • 또한 Virtual Thread 풀의 경우, 스트레스에 약한 모습을 보였습니다.
    • 허용치를 넘겨버리는 경우, 너무 쉽게 OOME 가 발생했습니다.

Why?

  • 해당 원인은 메모리 덤프를 통해 확인할수 있었습니다.
  • Platform Thread 사용시, 스레드풀은 전체 용량의 약 5% 만 차지하고 있었습니다.
  • 나머지 커넥션 관련 클래스전체 용량의 50% 이상을 차지하고 있었습니다.

메모리 덤프 - Platform Thread


메모리 덤프 - Virtual Thread


  • 따라서 어떻게 테스트 환경을 바꾸든지간에 최대 5~10% 의 성능 향상만 가능할것으로 보입니다.
    • 스레드를 늘리더라도 요청량을 그만큼 늘리는 경우, 커넥션 관련 클래스의 용량도 같이 늘어납니다.
    • 즉, 스레드 용량과 커넥션 관련 클래스의 용량 비율에 큰차이를 발생 시키기 어렵고
      이로인해 Virtual Thread 적용에 따른 메모리 절약 효과로 인한 큰 처리량을 기대하기 어려울것 같습니다.

결론

  • 대부분의 블로그에서 Virtual Thread 의 성능이 더 낫다고 기술하고 있어 아래의 결론을 내리기가 쉽지 않았는데요..
    하지만 많은 테스트 결과 아래처럼 결론 내릴수 있을것으로 보입니다.
  • Tomcat 10.1.15 이하 버전을 사용한다면 Virtual Thread 적용에 따른 처리량이 크게 증가하지 않을것으로 보입니다.
    (동시성 향상에 따른 처리속도는 증가할수 있습니다.)
  • 단, Platform Thread 환경에서 적절한 스레드풀 용량을 적용해주지 않는다면 Virtual Thread 가 유리합니다.
    (200개로 설정후 앞선 테스트 진행시, 평균 응답시간이 15초 였습니다.)
  • 결론적으로 높은 동시성이 필요한 환경에서는 당분간 Spring Web Flux 를 사용하는것이 나을것 같습니다.

Reference

Spring Boot Virtual Thread

Linux Tuninig

profile
매일매일 성장하고 싶은 백엔드 개발자입니다.

0개의 댓글