목차
Ruby on WebAssembly: 살짝 맛보기
Ruby 3.2에 추가된 WebAssembly 지원을 간단하게 테스트해봅시다.
2023-01-08#프로그래밍#Ruby#WebAssembly
💡 이 글은 작성된지 1년 이상 지났습니다. 정보글의 경우 최신 내용이 아닐 수 있음에 유의해주세요.
2022년 크리스마스에 정식 배포된 Ruby 3.2에는 WebAssembly 지원이 추가되었습니다. WebAssembly는 원래 JS 이외의 언어로 작성된 프로그램을 웹 브라우저에서 실행하기 위해 개발이 시작되었으나, 최근에는 브라우저를 벗어나서 모든 환경에서 안전하고 높은 성능으로 구동하는 기술로 주목받고 있습니다.
이 글에서는 Ruby로 작성한 간단한 코드를 WebAssembly로 포팅해보고, 제약 사항에 대해 간단히 알아보겠습니다.
비슷한 용어가 나오다보니 다소 헷갈릴 수 있습니다. 주요 사전 지식들을 가볍게 짚고 넘어가보겠습니다.
아래의 루비 코드를 WASM으로 패키징해봅시다.
# src/hello.rb
3.times do
puts "Hello, world!"
sleep 1
end
우선 사전에 빌드된 ruby.wasm을 내려받습니다. 이 파일에는 WASM 런타임에서 동작하는 ruby 바이너리가 들어있습니다.
$ curl -L https://github.com/ruby/ruby.wasm/releases/latest/download/ruby-head-wasm32-unknown-wasi-full.tar.gz -o ruby-wasm.tar.gz
$ tar -zxf ruby-wasm.tar.gz
$ mv head-wasm32-unknown-wasi-full/usr/local/bin/ruby ruby.wasm
이어서 wasi-vfs를 이용해 WASM 모듈로 패키징합니다.
$ mkdir -p build
$ wasi-vfs pack ruby.wasm \
--mapdir /src::./src \
--mapdir /usr::./head-wasm32-unknown-wasi-full/usr \
-o build/app.wasm
마지막으로 패키징된 WASM 파일을 실행해봅시다.
$ wasmtime run build/app.wasm -- src/hello.rb
Hello, world!
Hello, world!
Hello, world!
루비 코드가 정상적으로 실행되었습니다!
JSON 문자열을 객체로 파싱하고, 다시 문자열로 바꾸는 간단한 코드를 벤치마크 해봅시다.
# src/benchmark.rb
require "benchmark"
require "json"
'{"키": "값"}' => json_text
Benchmark.bm do |benchmark|
benchmark.report do
10_000.times do
JSON.parse(json_text) => json_obj
JSON.generate(json_obj)
end
end
end
아쉽지만 결과는 아직은 제법 성능 차이가 발생하고 있음을 보여주었습니다.
$ ruby src/benchmark.rb
user system total real
0.010922 0.000186 0.011108 ( 0.011108)
$ wasmtime run build/app.wasm -- src/benchmark.rb
user system total real
0.084124 0.000000 0.084124 ( 0.084120)
WebAssembly와 WASI는 아직 성장중인 기술인 만큼 여러가지 불완전한 부분이 있습니다. 대표적으로 컨텍스트 스위칭 기능이 없어 비동기 작업을 수행할 수 없습니다. 예를 들어, 스레드를 생성하는 코드를 이용한다면 아래와 같은 오류가 발생합니다.
$ wasmtime run build/app.wasm -- src/thread.rb
src/thread.rb:2:in `initialize': initialize() function is unimplemented on this machine (NotImplementedError)
from src/thread.rb:2:in `new'
from src/thread.rb:2:in `block in <main>'
from src/thread.rb:1:in `each'
from src/thread.rb:1:in `<main>'
아직은 초기 단계의 기술인 만큼 당장 이것을 어딘가에 적용한다기 보다는, 시대의 흐름에 탑승하기 위한 첫 걸음이라 생각한다면 좋을 것 같습니다.
관련된 글
Rails와 GitHub Actions에 커버리지 레포트를 달아보자
이 블로그의 CMS이기도 한 Shiori를 대폭 리팩토링하면서 테스트가 얼마나 잘 작성되어있는지 궁금해졌습니다.
Rails Global ID로 전역 객체 식별하기
Global ID는 Rails의 모든 객체를 식별할 수 있는 URI(Uniform Resource Identifier)입니다.
Ruby의 and와 &&는 다르다
Ruby로 프로그램을 짜다보면 반드시 밟게되는 지뢰가 있습니다. 바로 or 과 ||, 혹은 and 와 && 연산자의 우선순위가 달라서 발생하는 일입니다.
본 사이트의 저작물은 별도의 언급이 없는 한 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.
© 2011 - 2024 Hoerin Doh, All rights reserved.
작성한 댓글은 giscus를 통해 GitHub Discussion에 저장됩니다.