둠(Doom)을 브라우저에서? 0.16 FPS의 기적!
자바(Java) 코드를 브라우저에서 실행하기 위해 13겹의 추상화 계층(Inefficient Abstractions)을 사용, 둠(Doom)을 실행 시도
0.16 FPS의 처참한 성능으로 3개월의 게임 플레이 시간(Three Months of Gameplay)이 소요되는 비효율성을 보임
QEMU 에뮬레이터(QEMU Emulator)를 포함한 복잡한 환경 구성으로 인해 3~4시간의 부팅 시간(Boot Time) 발생
개선된 WASM 기반 환경에서는 15~20 FPS로 실행 가능하며, 부팅 시간 단축(Reduced Boot Time) 및 성능 향상 달성
13겹 추상화 계층의 성능 저하
본 사례는 자바(Java) 코드를 브라우저에서 실행하기 위해 13겹의 추상화 계층(Inefficient Abstractions)을 거치는 과정을 보여준다. 구체적으로, 브라우저의 JS 엔진, WebAssembly VM, Emscripten 런타임, QEMU x86 에뮬레이터, Linux 커널, OpenJDK JVM 등 여러 계층을 거치면서 단일 픽셀 룩업(Single Pixel Lookup)에 500~1,000개의 머신 인스트럭션이 소요되는 비효율성을 보여준다. 이러한 구조는 둠(Doom)의 0.16 FPS라는 처참한 성능으로 이어진다.
QEMU 에뮬레이터와 JIT 컴파일러의 비효율성
자바(Java)의 JIT 컴파일러(JIT Compiler)인 HotSpot C2는 8시간 동안 둠(Doom)의 렌더링 코드를 최적화하지만, QEMU 에뮬레이터가 이를 무시하고 자체적인 레지스터 매핑을 사용한다. 즉, JVM이 수 분 동안 최적화한 코드가 QEMU에 의해 재해석되는 것이다. 이러한 과정은 컴파일 시간(Compile Time)을 낭비할 뿐만 아니라, 3~4시간의 부팅 시간을 유발하는 주요 원인으로 작용한다. QEMU의 오버헤드(Overhead)는 성능 병목 현상의 핵심이다.
WASM 기반 환경으로의 개선
저자는 QEMU를 제거하고 Emscripten을 사용하여 OpenJDK를 WASM으로 직접 컴파일하는 방식으로 개선했다. 그 결과, 부팅 시간은 3초로 단축되었고, 둠(Doom)은 15~20 FPS로 실행 가능해졌다. 이는 WASM의 효율성(Efficiency)을 활용하여 성능 병목 현상(Performance Bottleneck)을 해결한 사례이다. 또한, JVM이 실제로 실행되는 코드를 컴파일하도록 함으로써 성능을 향상시켰다.
개발 과정에서의 교훈
본 사례는 자바(Java) 코드를 브라우저에서 실행하는 것이 기술적으로 가능하지만, 실용적인 측면(Practical Aspect)에서 많은 어려움이 있음을 보여준다. 특히, 13겹의 추상화 계층은 성능 저하의 주요 원인이며, 개발 생산성(Development Productivity)에도 부정적인 영향을 미친다. 따라서, 개발자는 기술적 가능성뿐만 아니라 실용성(Practicality)과 성능(Performance)을 고려하여 기술 선택을 해야 한다.