마이크로컨트롤러에서 Ruby 실행: MicroRuby와 PicoRuby의 메모리 효율성 비교

[JA] MicroRuby: True Microcontroller Ruby / Hitoshi HASUMI @hasumikin

작성자
RubyKaigi
발행일
2025년 05월 27일

핵심 요약

  • 1 MicroRuby 기반 R2P2 애플리케이션이 실용적인 RAM 소비량으로 성공적으로 구동되어, 풀스펙 Ruby의 마이크로컨트롤러 활용 가능성을 입증했습니다.
  • 2 mruby의 Pre-sym 및 Object Space 기능이 대규모 애플리케이션에서 mrbc보다 효율적일 수 있다는 '하미킨의 예상'을 실제 측정으로 뒷받침하며, 메모리 사용량 격차가 줄어들고 있음을 확인했습니다.
  • 3 마이크로컨트롤러 환경을 위한 선점형 태스크 스케줄링 및 커스텀 메모리 할당기를 구현하여 MicroRuby의 IoT 플랫폼 구축 역량을 강화했습니다.

도입

본 발표는 마이크로컨트롤러 환경에서 Ruby를 구동하는 두 가지 주요 접근 방식인 MicroRuby(mruby VM 기반)와 PicoRuby(mrbc VM 기반)의 메모리 효율성에 대한 심층적인 분석과 실제 구현 사례를 다룹니다. 기존에는 mrbc가 더 작은 메모리 footprint를 가진다는 인식이 지배적이었으나, 본 개발은 mruby의 특정 기능들이 대규모 애플리케이션에서 오히려 더 효율적일 수 있다는 가설을 검증하고자 진행되었습니다. 루비 협회 개발 보조금 프로젝트의 일환으로 진행된 이 연구는 mruby의 마이크로컨트롤러 생태계 확장을 목표로 합니다.

MicroRuby와 PicoRuby의 차이 및 메모리 소비 요인

  • PicoRuby: PicoRuby 컴파일러와 mrbc(mruby/c) 가상 머신의 조합입니다.
  • MicroRuby: PicoRuby 컴파일러와 mruby 가상 머신의 조합입니다.

초기 ‘Hello World’ 애플리케이션에서는 mrbc가 mruby보다 훨씬 적은 메모리를 소비하는 것으로 나타났습니다. 그러나 실제 IoT 애플리케이션과 같은 대규모 환경에서는 mruby의 다음과 같은 기능들이 메모리 효율성을 높일 수 있습니다.

  • IREP (Intermediate Representation): 컴파일러가 VM용으로 변환한 코드가 메모리에 전개된 객체로, 각 코드 블록(클래스, 모듈, 메서드 등)을 나타냅니다.
  • Pre-sym (Precompiled Symbols): mruby 3.0에 도입된 기능으로, 심볼 테이블과 IREP를 RAM이 아닌 ROM에 미리 전개하여 바이너리에 포함시키는 빌드상의 최적화입니다. 이는 mrbc나 CRuby에는 없는 mruby 고유의 기능입니다.
  • Object Space: mruby는 루비 객체를 하나의 할당 영역에 연속적으로 배치하여 메타데이터 오버헤드를 줄입니다. 반면 mrbc는 객체마다 개별 할당을 수행하여 메타데이터 및 패딩으로 인한 비효율성이 발생할 수 있습니다.

하미킨의 예상 (Hamikin’s Conjecture) 및 검증

이러한 mruby의 특성들을 바탕으로 ‘하미킨의 예상’이 제시되었습니다. 이는 소규모 애플리케이션에서는 PicoRuby가 유리하지만, 애플리케이션 규모가 커질수록 MicroRuby의 메모리 소비 증가율이 완만해져 어느 시점에서 PicoRuby와 교차하는 ‘건배 지점(Kampai Point)’이 발생할 것이라는 가설입니다.

이 가설을 검증하기 위해 PicoRuby용으로 개발된 R2P2(쉘과 유사한 대규모 애플리케이션)를 MicroRuby에 포팅하는 작업이 진행되었습니다.

구현 세부 사항

  1. 선점형 태스크 스케줄링: mruby에는 없는 기능으로, R2P2와 같은 OS 유사 애플리케이션 구동에 필수적입니다. C Ruby의 스레드와 유사하게, 인터럽트를 통해 CPU 리소스를 여러 태스크에 할당하는 방식입니다. mrb_context 구조체를 활용하여 태스크를 구현하고, 10ms마다 태스크를 전환하는 메커니즘을 도입했습니다.
  2. GC (Garbage Collection) 처리: 여러 mrb_context 인스턴스가 존재할 때, GC의 루트 스캔 단계에서 모든 컨텍스트를 최상위 레벨로 마크하여 불필요한 객체 회수를 방지하도록 GC 로직을 수정했습니다.
  3. 커스텀 메모리 할당기 (est_alloc): 마이크로컨트롤러 환경에서는 기존 newlibmalloc이 메모리 사용량 보고 기능을 제공하지 않으므로, mrbc의 내장 할당기를 기반으로 est_alloc이라는 커스텀 할당기를 개발하여 정확한 메모리 측정을 가능하게 했습니다.

메모리 측정 결과 및 결론

R2P2 애플리케이션을 MicroRuby에 포팅하여 측정한 결과, Wi-Fi 연결 상태에서 MicroRuby는 약 109KB의 RAM을 사용했습니다. 이와 비교하여 PicoRuby는 초기 49KB에서 R2P2 관련 Gem을 수동으로 로드했을 때 78KB를 사용했습니다. 약 30KB(30%)의 차이로 메모리 소비량 격차가 줄어들었으며, 이는 ‘하미킨의 예상’이 실제와 부합할 가능성을 시사합니다. Raspberry Pi Pico W(264KB RAM)에서는 다소 타이트할 수 있으나, Pico 2W(520KB RAM)에서는 충분히 실용적인 범위에 있음을 확인했습니다.

결론

본 개발을 통해 MicroRuby 기반의 R2P2 애플리케이션이 실용적인 RAM 소비량으로 구동될 수 있음을 성공적으로 입증했습니다. 이는 mruby의 Pre-sym 및 Object Space와 같은 기능이 대규모 애플리케이션에서 mrbc에 비해 경쟁력 있는 메모리 효율성을 제공할 수 있다는 '하미킨의 예상'을 뒷받침하는 중요한 결과입니다. 곧 풀스펙 Ruby가 마이크로컨트롤러 환경에서 더욱 쉽게 활용될 수 있을 것으로 기대됩니다. 비록 IRB에서 Pre-sym 관련 버그가 남아있지만, 이번 성과는 마이크로컨트롤러 상에서 Ruby의 활용 가능성을 크게 확장할 것입니다. 본 프로젝트의 루비 협회 개발 보조금은 우크라이나에 기부되어 자유로운 프로그래밍 환경의 가치를 되새겼습니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!