Virtual Thread Pinning Issue

ISSUE: Pinning inside synchronized


대부분의 애플리케이션은 RDB를 통해서 영속화 합니다. 제가 관리하는 서비스 경우에는 MySQL 를 사용하고 있습니다. 대부분의 jdbc-driver 코드 내에는 동시성 이슈를 처리하기 위해서 synchronized 를 이용해서 구현되어 있습니다. 이것 때문에 Carrier Thread에서 lock이 걸리는 일명 pinning(고정) 이슈가 있으며, 이것 때문에 성능 저하가 큽니다.

대표로 jdbc-driver를 예로 들긴 했지만 jdbc-driver 만의 문제는 아닙니다. 기존 레거시 라이브러리에서 synchronized 를 사용한다면 다 문제가 될 수 있습니다. 다행히 Spring 에서는 이 문제를 대부분 해결한 버전이 릴리즈 됐습니다.

Pinning Issue on Virtual Thread

Pinning 이슈에서 대해서 간단하게 알아보겠습니다. 먼저 Virtual Thread에 대한 구조를 알아야합니다.

// TODO 이거 제대로 작성해야하는데 귀찮음. 정리가 잘 된 다른 블로그 글을 링크할까 고민 중…

Pinning Solution

해결책은 의외로 간단합니다. synchronized -> ReteerantLock 로 변경하면 끝이죠.

MySQL Driver

mysql에서 이미 대응 중이며, MySQL Connector/J(jdbc-driver) 9.0 버전에서 해결될 예정이라고 합니다.
참고: https://bugs.mysql.com/bug.php?id=110512

여러분들도 사용하시는 jdbc-driver나 라이브러리의 릴리즈 노트 또는 코드를 확인하시길 바랍니다.

MariaDB Driver

MariaDB vs MySQL OPS by virtual thread, platform thread Graph

mysql 사촌 뻘인 MariaDB의 경우에는 벌써 Virtual Thread를 MariaDB Java connector 3.3.0 적용했네요.
거기에 https://mariadb.com/resources/blog/benchmark-jdbc-connectors-and-java-21-virtual-threads/ 블로그에 벤치마크 정보까지 보여주는군요.

힘내라 MySQL!!!

출처: https://m.animalplanet.co.kr/contents/?artNo=3749

아직은 시기상조?

하지만 non-blocking 기반으로 구현된 driver(ex: MariaDB)를 사용한다면 Virtual Thread를 긍정적으로 검토해 볼 수 있습니다. 그 외 아래와 같은 경우 좋다고 봅니다.

  1. Edge 서비스(Api Gateway)
  2. 처리량이 중요한 서비스: 단, Latency는 좀 부족할 수 있습니다. 그럼에도 리소스 대비 처리량은 우수합니다.

이미 Java 커뮤니티에서는 synchronized 지시어 를 많이 제거하고 있습니다. 제가 봤을 때는 시간의 문제라고 보고 있으며, 이제 타 플랫폼의 경량 스레드(고루틴, 코루틴)를 기존 Thread 모델 기반 코드 베이스에서 편하게 사용할 수 있는 시대가 곧 다가올 거라고 봅니다.

추가로 JEP 425: Virtual Threads (Preview) 에서 추후 Pinning 이슈를 회피할 수 있다고 했습니다. 이게 된다면 기존 레거시 라이브러리 상에서도 편하게 Virtual Thread를 사용할 수 있을 것 같네요. (하지만 native 호출에 대해서는 제약은 유지한다고 하네요)

JEP-425 일부 발췌

...
 1. When it executes code inside a synchronized block or method, or
 2. When it executes a native method or a foreign function.
...
In a future release, we may be able to remove the first limitation above (pinning inside synchronized). The second limitation is required for proper interaction with native code.

그래서 우리가 할 수 있는 것은?

  • 공유 자원 동시성 제어가 필요하면 synchronized 를 사용하지 않고 ReentrantLock을 사용.
  • 사용하는 라이브러리에 Pinning 이슈가 있는지 확인하기(모든 라이브러리를 일일이 찾기는 힘드니 성능테스트 추천)
    -Djdk.tracePinnedThreads=full or short JVM 옵션으로 Pinning 이슈 추적 가능
  • 기다린다 – 언젠가 Java 커뮤니티에서 다 해결해 줄 겁니다.-

1 thought on “Virtual Thread Pinning Issue”

Leave a Comment