Roite 개발은 여러 중요한 단계를 거쳤습니다. 첫 번째 이정표는 Rust로 작성된 WebAssembly 기본 구현 학습서인 “Gora Book”을 루비 버전으로 재구현하는 것이었습니다. 이 과정에서 Wasm 바이너리 파싱 및 VM 실행 루프의 기본 원리를 이해했습니다. 다음으로, WebAssembly 코어 스펙의 기본 명령어 192개를 구현하는 데 집중했습니다. 특히 i32, i64, f32, f64와 같은 4가지 숫자 타입에 대한 유사한 명령어들을 효과적으로 처리하기 위해 코드 생성기를 활용했습니다.
이후 실제 프로그램을 실행하기 위한 시도로 Rust로 작성된 그레이스케일 변환 프로그램을 Roite에서 구동하려 했으나, 메모리 할당 문제와 Rust의 panic
이 unreachable
로 번역되는 문제에 직면했습니다. 이러한 디버깅 과정에서 llvm-test-suite
의 Wasm 테스트 스위트를 활용하여 숫자 명령어의 정확성을 검증하고, 마침내 그레이스케일 프로그램 실행에 성공했습니다.
가장 도전적인 단계는 Roite 위에서 루비를 실행하는 것이었습니다. 이를 위해 37개의 WASI(WebAssembly System Interface) 함수, 특히 wasi_snapshot_preview1
버전을 구현해야 했습니다. 초기에는 ruby --version
명령어가 작동했지만, require
와 같은 파일 시스템 관련 기능은 작동하지 않았습니다. 이 문제는 pre-opens
메커니즘을 정확히 이해하고 구현함으로써 해결되었습니다. pre-opens
는 보안상의 이유로 Wasm 런타임이 호스트 파일 시스템에 직접 접근할 수 없으므로, VM 시작 시 미리 등록된 파일 디스크립터를 통해 접근 권한을 부여하는 핵심 메커니즘입니다. 이를 구현한 후, 표준 루비 명령어도 경고 없이 정상적으로 실행될 수 있었습니다.
성능 최적화 또한 중요한 부분이었습니다. 블록 점프 명령어의 타겟 종점 위치를 동적으로 계산하는 대신 미리 계산하여 캐싱함으로써 실행 시간을 43% 단축했습니다. 또한, 내부 객체 인스턴스 생성이 병목 현상을 일으키는 것을 확인하고, 자주 사용되는 정수(0~64, -1) 인스턴스를 메모이제이션하여 속도를 1초가량 향상시켰습니다. WASI의 적용은 벤치마크에서 Ruby 7.1의 경우 52%, 3.4의 경우 57%의 실행 시간 단축 효과를 보여주며 매우 효과적임을 입증했습니다.