Scala 3가 우리를 느리게 만들었나?

1 day ago 1

  • Scala 2.13에서 Scala 3로의 코드베이스 마이그레이션 과정에서 예상치 못한 성능 저하가 발생
  • 초기 테스트와 배포 환경에서는 모든 지표가 정상이었으나, 몇 시간 후 Kafka 지연(lag) 이 증가
  • 부하 테스트 결과, 세분화된 메시지 처리 시 처리율 급감 현상이 확인
  • async-profiler 분석을 통해 Quicklens 라이브러리의 체인 평가 비효율 버그가 원인으로 드러남
  • 라이브러리 업데이트 후 성능이 복구되었으며, Scala 버전 간 라이브러리 동작 차이에 대한 주의 필요성 강조

서비스 마이그레이션 과정

  • 기존 서비스는 Scala 2.13에서 Scala 3.7.3으로 이전
    • 매크로를 사용하지 않는 데이터 수집 중심 서비스였으며, 성능이 중요한 구성
    • 의존성, 컴파일러 옵션, 타입 및 문법 변경을 적용 후 컴파일 성공
  • 테스트 환경과 단계적 배포에서도 로그와 메트릭 모두 정상으로 나타남
    • 인프라, JVM, 애플리케이션 수준의 지표 모두 건강한 상태로 확인

원인 불명의 성능 저하

  • 배포 후 약 5~6시간 뒤 Kafka lag 증가 현상 발생
    • 데이터 스파이크가 아닌 상황에서도 인스턴스당 처리율 감소
    • 롤백 후 처리율이 즉시 복구되어 코드 변경이 원인임을 확인

성능 분석 및 원인 추적

  • 부하 테스트에서는 초기에는 성능 회귀가 재현되지 않음
    • 메시지의 세분화 및 이질적 페이로드에서만 처리율 급감이 발생
  • 의존성 라이브러리(직렬화, DB SDK, Docker 이미지, 설정 라이브러리 등)를 하나씩 되돌려 테스트했으나 변화 없음
  • async-profiler로 CPU 프로파일링 수행 결과,
    • Scala 3에서는 JIT 컴파일러와 디코딩 단계의 CPU 점유율 급증
    • Flamegraph 상단에서 Quicklens 호출이 전체 CPU 시간의 절반 차지
    • Scala 2.13에서는 동일 호출이 0.5% 수준에 불과

문제의 근본 원인

  • Quicklens 라이브러리의 체인 평가 비효율 버그가 Scala 3에서 발생
    • 관련 수정은 GitHub PR #115에 반영
    • 라이브러리 업데이트 후 Scala 3과 2.13 간 성능 차이 해소

교훈 및 권장 사항

  • 라이브러리의 메타프로그래밍 의존성이 Scala 버전 간 성능 차이를 유발할 수 있음
  • 마이그레이션이 정상적으로 완료되어도, 핫스팟과 병목 구간을 벤치마크해야 함
  • 성능이 중요한 서비스에서는 “잘 동작한다”는 가정 대신, 실측 기반 검증이 필수
  • 코드가 아닌 벤치마크가 병목을 드러내는 상황을 방지하기 위한 사전 점검 필요

Read Entire Article