Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
emruby: ブラウザで動くRuby
Search
Yusuke Endoh
April 23, 2021
Programming
0
15
emruby: ブラウザで動くRuby
銀座Rails #32
https://ginza-rails.connpass.com/event/207692/
Yusuke Endoh
April 23, 2021
Tweet
Share
More Decks by Yusuke Endoh
See All by Yusuke Endoh
12年前の『型システム入門』翻訳の思い出話
mame
12
1.6k
Good first issues of TypeProf
mame
4
5.5k
Revisiting TypeProf - IDE support as a primary feature
mame
1
2.1k
error_highlight: User-friendly Error Diagnostics
mame
0
13
TRICK 2022 Results
mame
0
10
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
mame
0
19
Enjoy Ruby Programming in IDE and TypeProf
mame
0
20
TypeProf for IDE: Enrich Development Experience without Annotations
mame
0
15
Ruby 3の型解析に向けた計画
mame
0
20
Other Decks in Programming
See All in Programming
ROS 2のZenoh対応とZenohのROS 2対応
takasehideki
2
250
2024-10-02 dev2next - Application Observability like you've never heard before
jonatan_ivanov
0
150
[PHPカンファレンス沖縄2024]「無理なくできるだけ安全に」テストもないレガシーコードをリファクタリングするテクニック
ikezoemakoto
3
110
XP2024 っていう国際会議に行ってきたよの記 / XP2024 Conference Report
bonotake
4
160
Micro Frontends for Java Microservices - dev2next 2024
mraible
PRO
0
190
Kubernetes上でOracle_Databaseの運用を楽にするOraOperatorの紹介
nnaka2992
0
150
Cohesion in Modeling and Design
mploed
3
180
Assembling the Future: crafting the missing pieces of the Ruby on Wasm puzzle
skryukov
0
120
CSC509 Lecture 03
javiergs
PRO
0
130
上手に付き合うコンポーネントテスト
quramy
3
1.2k
Iteratorでページネーションを実現する
sonatard
3
700
ACES Meet におけるリリース作業改善の取り組み
fukucheee
0
120
Featured
See All Featured
GraphQLとの向き合い方2022年版
quramy
43
13k
The World Runs on Bad Software
bkeepers
PRO
65
11k
Code Review Best Practice
trishagee
62
16k
A Modern Web Designer's Workflow
chriscoyier
692
190k
What the flash - Photography Introduction
edds
67
11k
Teambox: Starting and Learning
jrom
131
8.7k
Agile that works and the tools we love
rasmusluckow
327
21k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
249
21k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9k
Building a Scalable Design System with Sketch
lauravandoore
459
32k
Six Lessons from altMBA
skipperchong
26
3.4k
No one is an island. Learnings from fostering a developers community.
thoeni
19
2.9k
Transcript
emruby: ブラウザで動くRuby 銀座Rails #32 Yusuke Endoh 1
自己紹介:遠藤侑介 (@mametter) • クックパッドで働くフルタイムRubyコミッタ • Ruby 3添付の静的解析ツールTypeProf作ってます • https://github.com/ruby/typeprof •
でも今日はぜんぜん違う話をします 2
emruby: ブラウザの上で動くRuby https://mame.github.io/emruby/ 3
emrubyの狙い • ブラウザでRubyが動くのは楽しい • 頑張ればTryRuby(お試し環境)くらいにはなるか? • 将来的にJavaScriptの代替になるかはWASM次第? • Rust /
Go / KotlinなどもWASM出力に対応してるので • おことわり • この発表にはRailsもRuby言語もほとんど出てきません • Rubyのビルドの知識が少し身につきます 4
Rubyをブラウザで動かす関連研究 • Opal: JavaScriptで書かれたRubyインタプリタ • https://github.com/opal/opal • Artichoke: Rustで書かれたRubyインタプリタ(WASM出力対応) •
https://github.com/artichoke/artichoke • repl.it: Ruby 1.8をEmscriptenしたもの(らしい) • https://github.com/replit-archive/emscripted-ruby • Ruby on WebAssembly: mrubyをEmscriptenしたもの • https://github.com/blacktm/ruby-wasm • RubyのNaClサポート(2012~2017) • よくまとまってる記事 • https://blog.unasuke.com/2021/products-about-webassembly-and-ruby/ 5
アジェンダ • ➔WASM / Emscriptenとは • emrubyが動くまで • まとめ 6
WebAssembly (WASM) • ブラウザの上で動く実行ファイル形式 • 2017年頃からメジャーブラウザが対応している • JavaScriptより速くて (?) 小さいらしい
7
Emscripten • C/C++のプログラムをWASMに変換するコンパイラ • LLVMベース • デモ一覧(古そう):https://github.com/emscripten- core/emscripten/wiki/Porting-Examples-and-Demos • http://kripken.github.io/boon/boon.html
• https://files.unity3d.com/jonas/AngryBots/ • http://coolwanglu.github.io/vim.js/emterpreter/vim.html 8
Emscriptenの基本的な使いかた 9 #include <stdio.h> int main() { printf("hello, world!¥n"); return
0; } emcc hello.c –o hello.js && node hello.js emcc hello.c –o hello.html
アジェンダ • WASM / Emscriptenとは • ➔emrubyが動くまで • まとめ 10
前提知識:Rubyのふつうのビルド • Rubyソースのディレクトリで次のコマンドを打つ • ./configure: 環境ごとにビルド方法を調整する • どのシステム関数が使えるか、コンパイラオプションが使えるか • OS、コンパイラ、バージョンなどの違いを調べる
• make: ソースコードをコンパイルする • まずminirubyという制限版ruby実行ファイルを作る • minirubyを使ってスクリプト(Rubyで書かれている)を動かし、 拡張ライブラリや最終的なruby実行ファイルを作る 11 ./configure && make
話の流れ • minirubyをWASMにする • 本当のrubyをWASMにする • 最終目標:irbを動かす? 12
./configure && makeのEmscripten化 • Emscriptenはconfigure+makeに対応している • emconfigure / emmakeはビルドをうまくだまして Emscriptenコンパイラを使わせる
• これだけ……ではない • 実用プログラムがゼロ変更でビルドできることは無いと思う 13 emconfigure ./configure && emmake make
Emscriptenが未実装のC関数に対処する • 問題:Emscriptenで利用できないC関数がいっぱいある • popenがない • pthread_createはあるがpthread_killはない • pthread_createはあるがpthread_attr_getguardsizeがない •
pthread_sigmaskはあるけど実際には動かない (!) 、など • configureの盲点をつくような未実装がいろいろあった • 対処:Rubyのconfigureを改善して対応した • コミッタなので、Ruby側を直接変更しまくった 14
Rubyは関数の引数の数にルーズだった • C言語では、関数に引数を余分に渡しても良い (!?) • C言語仕様違反だが、 多くのCコンパイラで動く • Rubyはこれに依存していた •
Emscriptenのオプションで 対応した • -s EMULATE_FUNCTION_POINTER_CASTS=1 15 int foo(int a) { printf("%d¥n", a); } int main() { int(*foo2)(int,int) = (int(*)(int,int))foo; foo2(42, 43); // 42 } 1引数の関数fooを2引数で呼び出す例
miniruby.wasmできた! • 2018年はこの段階で公開した • 残念なお知らせ • EMULATE…オプションがEmscirptenから削除された • コンパイルできなくなった •
どうしたか • 放置した → 3年経ったら、Ruby側が直っていた! • 微修正で2021年1月に再ビルドに成功した 16
話の流れ • minirubyをWASMにする • ここまでできた • 本当のrubyをWASMにする • 最終目標:irbを動かす? 17
ruby.wasmを作るには • ふつうのrubyのビルドには、minirubyが必要 • しかしminiruby.wasmはLinuxで実行できない • クロスコンパイルする • ビルド環境とはちがう環境の実行ファイルを作ること •
Linuxでruby.exe(Windowsの実行ファイル)を作る、とか • 今回はLinuxでruby.wasmを作る • emconfigureはかえってややこしくなるのでやめた 18
Rubyのクロスコンパイル • Rubyのconfigureはクロスコンパイルに対応している • minirubyの代わりにビルド環境のrubyを使ってくれる • これで一応ruby.wasmはできた • が、全然動かないのでデバッグ&ドキュメント&ソース読み 19
$ ./configure ¥ --build x86_64-pc-linux-gnu ¥ --host wasm32-unknown-emscripten ¥ CC=emcc LD=emcc AR=emar RANLIB=emranlib $ make ビルド環境 対象環境 Emscripten
問題:Rubyの保守的GC • 保守的GCとは • マシンスタックの値がオブジェクトの参照であると仮定して マーク対象とするガベージコレクタの方式 • https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%BB%E3%82%A2%E3%83%B3%E3%83%89%E3%83%BB%E3%82%B9%E3%82%A4%E3%83%BC%E3% 83%97#%E4%BF%9D%E5%AE%88%E7%9A%84%E3%81%AA%E3%82%AC%E3%83%99%E3%83%BC%E3%82%B8%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%BF •
つまり意図的にC言語仕様違反なメモリアクセスをする • Emscriptenのメモリモデルでは全然動かない • 対処:Emscriptenが保守的GC用のAPIを用意していた • emscripten_scan_stack / emscripten_scan_registers • スタックの先頭と終端がわかる、これらを使うようにした 20
余談:Fiberに対応する(未完) • Rubyは2018年末にFiberの一部をアセンブリで実装した • Emscriptenでx86アセンブリはコンパイルできないので コンパイルエラーになっていた • 対処:EmscriptenのAPIを使って実装した • emscripten_fiber_init
/ emscripten_fiber_swap • コンパイルオプション -s ASYNCIFY と合わせて使う • miniruby.wasmでは動いたが、ruby.wasmでは動かない • 原因未解明、今後の課題 • とりあえずFiber使わなければ問題ない 21
問題:動的リンクができない • つまり、拡張ライブラリの require ができない • require "ripper"したらripper.soを動的リンクする • しかしEmscriptenは動的リンクに未対応(たぶん)
• 解決:ripperを静的リンクした • 他にも必要な拡張ライブラリを色々足した 22 $ ./configure ¥ --with-static-linked-ext --with-ext=ripper … $ make
その他Emscripten特有っぽい話 • リンクが失敗する(htonsが見つからない、とか) • -lcでlibcを明示的にリンクすれば動いた • -fstack-protectorも対応してないようなので消した • すぐメモリ不足エラーになる •
Emscriptenはデフォルトでメモリサイズを固定確保する • サイズ可変にするオプションをつけた (-s ALLOW_MEMORY_GROWTH=1) • stack overflowの検出が動かないので止めた、など 23
ruby.wasmできた! • require "ripper.so"も動く • ある程度複雑なRubyスクリプトも動く 24
話の流れ • minirubyをWASMにする • 本当のrubyをWASMにする • ここまでできた • 最終目標:irbを動かす? 25
irbを動かすのに必要なもの • Rubyインタプリタ(できた) • ripper.soなどの拡張ライブラリ(できた) • irbのソースコード(あるけどまだ組み込んでない) • 端末エミュレータ(無い) 26
仮想ファイルシステム • Emscriptenのfile_packagerツールで作れる • irbやrubygemsなど必要なRubyソースコードをまとめた • fs.jsとfs.dataができた • がんばってロードできるようにした •
コンパイルオプションに-s FORCE_FILESYSTEM=1追加 • fs.jsを<script>で呼ぶだけ……なのだが意外と苦労した 27
xterm.jsを組み込む • xterm.js: ブラウザで動く端末エミュレータ • https://xtermjs.org/ • VS Codeでも使われている •
残念なお知らせ • Emscriptenは標準入出力の実装がいまいち • とりあえずの対応 • ライン編集はxterm.js側でやり、irbには行単位で送る • reline(irbの新しい編集機能)の活用は今後の課題 28
ということで https://mame.github.io/emruby/irb/ 29
CPU 100%を防ぐ • Emscriptenの生成物はほぼ同期で動く(asyncでない) • 入力待ちをポーリングでやるみたい(ゲーム想定?) • 対処:別スレッド(Web Worker)で動かすようにした •
通信方法はvim.wasmに習った(SharedArrayBuffer使用) https://rhysd.hatenablog.com/entry/2019/06/13/090519 • 残念なお知らせ:5月に動かなくなる見込み 30
ということで • (かなり妥協したけど)irbがブラウザで動いた! • rubygems、did_you_meanなども一応動いているっぽい 31
落ち穂拾い • ruby.wasmのサイズ:29 MB • コンパイルオプションで調整して8 MB • -Os: 省サイズ重視で最適化する
• -g0: デバッグ情報を省く 32
Emscripten所感 • 夢の技術ではない • 現実のC言語コードをゼロ変更でビルドできることは無い • いっぱい問題に遭遇する • が、とてもよくできている •
一生懸命調べればたいてい対処方法やAPIがある • 検索に頼らずドキュメントを通して読むのが早道 • 動いたらとても嬉しい 33
まとめ • ブラウザで動くRuby、emrubyを紹介しました • 大体Ruby側で対応したのでたったこれだけでビルドできる 34 $ ./configure ¥ --build
x86_64-pc-linux-gnu ¥ --host wasm32-unknown-emscripten ¥ --with-static-linked-ext ¥ --with-ext=ripper,date,strscan,io/console,…,psych ¥ optflags=-Os debugflags=-g0 ¥ CC=emcc LD=emcc AR=emar RANLIB=emranlib $ make
今後の予定 • ほそぼそとメンテナンスするつもり • WASMが大ヒットする日に備える • そのとき「RubyもWASM対応してます」と言いたい • RubyからJSやDOMを操作できたらいいなあ •
当面はOpalを使うのがいいと思います • WASM版TryRubyができたらいいなあ • Opalであまり問題はないですが 35