RubyKaigi 2024の予習メモ・リンク集
2024/5/11
間違いがあったり、他に予習したほうが良さそうなテーマがあったら教えてください。
Concurrency & Parallelism (GVL, Ractor, M:N, async)
これ全部同じ項でいいのか?
- 並行(concurrency)と並列(parallelism)
- 本当に同時に実行されるのが並列(雑な説明)
- 並行であっても並列とは限らないが、並列であって並行でないことはない
- GVL (Global VM Lock)
- Rubyで並列に実行されるThreadの数を高々1つに制限する機構
- = Rubyでは並列計算はできない
- ただし、I/O(ファイルの読み書きやネットワークアクセス)はこの制限を無視できる
- マルチスレッドプログラミングを簡単にする機構として導入されている
- 複数のThreadから同じ変数にアクセスしてもデータが壊れない(データレースが起きない)のはGVLのおかげ
- = 真に同時に書き換えることが不可能になっているから
- .oO (そうは言ってもレースコンディションがすべてGVLで防がれるわけではない)
- 複数のThreadから同じ変数にアクセスしてもデータが壊れない(データレースが起きない)のはGVLのおかげ
- かつてはプロセスグローバルだったが、現在は1つのRactorにつき1つのGVLがある
- 異なるRactorに属する処理同士であれば並列に実行可能
- CRubyのコード上では
gvl
の言葉は廃される方向にあり、thread_sched
と呼ばれている
- Rubyで並列に実行されるThreadの数を高々1つに制限する機構
- Ractor
- M:N Threads
- Feature #19842: Introduce M:N threads
- ささださんの記事・発表群
- M:Nスレッドによる軽量な並行処理への挑戦
- Rubyの並列並行処理のこれまでとこれから - クックパッド開発者ブログ(Ractorの項と同じ記事)
- Making MaNy threads on Ruby (RubyKaigi 2022)
- "Ractor" reconsidered (RubyKaigi 2023)
- Ruby 3.3で実験的に導入された新しいスレッドスケジューラ
RUBY_MN_THREADS=1
で有効化できる
- Ruby 1.9以降、Ruby Threadとpthreadは常に 1:1 の関係(新しいThreadを起動すると新しいpthreadが起動する)にあったが、M:Nを有効にするとこの関係が崩れる
- GolangのGoroutineスケジューラが近いモデルっぽい?
- async (socketry/async)
- ioquatixが作っている、イベントループで非同期I/Oを実現するライブラリ
- 非同期I/O
- epoll, io_uring
- 非同期I/O vs マルチスレッド
- 大量のI/Oイベントがあるとき、スレッドの起動やコンテキストスイッチのオーバーヘッドが無視できなくなる
- e.g. 大量のリクエストをさばくサーバー
- シングルスレッドでの非同期I/Oであればマルチスレッド特有の悩みはない
- 裏を返せば、並列計算は当然できない
- 非同期I/Oのほうがキャンセルを扱いやすい
- 大量のI/Oイベントがあるとき、スレッドの起動やコンテキストスイッチのオーバーヘッドが無視できなくなる
- Falcon (socketry/falcon)
- asyncを使って実装されたRack server
- 関連する並列実行モデル
- 知りたい
Parser
- Lrama (ruby/lrama)
- parse.y(BNFによるRubyの文法の定義と "action" の定義)からparse.c(パーサーの実装)を生成するツール(パーサージェネレーター)
- Lrama LRパーサジェネレータが切り開く、Rubyの構文解析の未来
- Lramaの開発者のかねこさんの記事。手書きパーサーに対するパーサージェネレーターの優位性や、BisonをLramaで置き換えた理由が語られている
- "BNFは文法が理解しやすい" というのはたしかに
- Lramaの開発者のかねこさんの記事。手書きパーサーに対するパーサージェネレーターの優位性や、BisonをLramaで置き換えた理由が語られている
- Ruby Parser開発日誌 (13) - Ruby Parser Roadmapをつくった - かねこにっき
- こちらもかねこさんの記事。Lramaの目指すところが書かれている
- Rubyプログラムを実行するときのパースと、
RubyVM::AbstractSyntaxTree
で使われる - Lramaの "lr" はLR parserのLR?
- Prism (ruby/prism)
- Cで実装された "手書き" のパーサー
- BNFから生成するのでなく、すべて手で実装されている
- Prism:エラートレラントな、まったく新しいRubyパーサ
- Prismの開発者のKevinの記事
- Prism in 2024 - Rails at Scale
- こちらもKevinの記事。Ruby 0.01からのパーサー史、Prismの目指すところが書かれている
- Rubyコードから呼び出しやすい形で作られており、勢いよくparser gemのユースケースを置き換えている
- JRubyやTruffleRubyのパーサーにも採用されている
- Cで実装された "手書き" のパーサー
- パーサージェネレーター(Lrama)とパーサー(Prism)の違い
- パーサージェネレーター = BNFなどで定義された文法の定義からパーサーを生成するもの
- パーサーは…… パーサー
- "parse.y" = パーサージェネーターの入力となる文法の定義
- yaccやBison(ともにパーサージェネレーター)が受け付ける形式
- LramaはBison互換に作られている
- Lrama vs Prism?
- それぞれ方針が異なる2つの実装だが、どちらもCRubyのスタンダードなパーサーの立ち位置をめざしている
- Ruby 3.2まではparse.yからBisonが生成したparse.cが唯一のパーサーだった
- Ruby 3.3ではparse.yからLramaが生成したparse.cがデフォルト
- parse.yの処理において、LramaはBisonの100%互換なのに対し、Prismは現時点ではパースできない文法がわずかに存在する
- 一方、生成されるASTの構造はPrismのもののほうが扱いやすい、とされている
- ので、いずれのパーサーを採用するにせよ、外向きのインタフェースはPrismのものにする、らしい?
- 正直よくわかっていない
- それぞれ方針が異なる2つの実装だが、どちらもCRubyのスタンダードなパーサーの立ち位置をめざしている
- LR(0), LALR(1), etc.
- 構文解析(パース)のアルゴリズムのこと
- そのアルゴリズムで受理できる言語の集合のことも指す
- Feature #19719: Universal Parser
YJIT
- yjit/yjit.md
- YJIT: a basic block versioning JIT compiler for CRuby (VMIL 2021)
- YJITのメイン?開発者のMaximeの論文
- YJIT Benchmarks
- YJITを使うとどれぐらい速くなるかをnightlyで示している
- RubyKaigi 2023のKeynote(Optimizing YJIT’s Performance, from Inception to Production)では、このベンチマークをいかに安定させるか(e.g. ハイパースレッディングを切る)という話もしてた、と思う
Typing (RBS, Sorbet, TypeProf)
- RBS (ruby/rbs)
- Rubyコードの型定義を記述するための言語
- ruby/gem_rbs_collection
- RBSを同梱していないGemの型定義の集積リポジトリ
- DefinitelyTypedのRuby版と考えるとわかりやすい
- Steep (soutaro/steep)
- soutaroさんを中心に開発が進んでいる、RBSをを使った静的型検査器
- Sorbet (sorbet/sorbet)
- 決済プラットフォームのStripeが開発している静的型検査器
- RBIという、RBSとは異なるアノテーションを用いて型の記述を行う
- TypeProf, TypeProf v2 (ruby/typeprof)
- mameさんが開発している、型定義を用いずに型解析を行うツール
- RubyKaigi 2023の発表( Revisiting TypeProf - IDE support as a primary feature )ではTypeProf v1の課題がその速度にあったと捉え、IDEの入力補完的なシーンでも実用的な速度を出せる形に作り直したい、と整理していた
- と思う
- 関連: Rubyと型についてのポエム - まめめも
- 型アノテーションに対するMatzの考え
- 「自分の未来予測を信じてちょっと意地を張ってみる」 まつもとゆきひろ氏がRubyに型宣言を入れない理由
- 「作りたいものをいかに早く完成させるかが正義」 まつもとゆきひろ氏が語る、ソフトウェア開発におけるベロシティの重要性
- それぞれMatzチャンネルで配信されたPodcast? の書き起こし(#17 動的型付け言語と大規模開発#1, #18 動的型付け言語と大規模開発#2)
- まだあったら探したい
Wasm, ruby.wasm
- ruby/ruby.wasm
- 実はこのリポジトリに何があるのか分かっていない
- ruby.wasm ハッキングガイド
- ledsunさんのスライド
- Wasm/WASI 101
- Wasm = WebAssembly
- 仕様は https://webassembly.github.io/spec/core/
- Wasmの仕様自体は命令セットとVMの仕様の定義にすぎず、実装は伴わない
- Webブラウザ, wasmtime, Wasmerなどの実行環境(embedder)で動作する
- WASI = WebAssembly System Interface
- Wasm = WebAssembly
Tooling
- IRB (rubyirb)
- ruby-lsp (Shopify/ruby-lsp)
- ViniciusがShopifyで開発している、Ruby用の新しいLSP
- READMEに "Ruby DX Slack" への招待リンクもあるので見ると面白いかも
Other Rubies
- mruby (mruby/mruby)
- mruby/c (mrubyc/mrubyc)
- あとで予習する
- JRuby
- TruffleRuby
- GraalVM
- PicoRuby (picoruby/picoruby)
- hasumikinさんが開発している、Raspberry Pi Pico (264 KB RAM, 2 MB ROM) で動かすことを目指す
- monoruby (sisshiki1969/monoruby)
- monochromeさんが開発している、Rust製のフルスクラッチRuby処理系
Misc
- Object Shapes (Feature #18776: Object Shapes)
- Rubyオブジェクトの構造(Shape)をキャッシュすることで、インスタンス変数等へのアクセスを高速化する最適化
- Shape = インスタンス変数(ivar)の定義順とfrozenness
- 同じクラスのオブジェクトでもivarの定義順が異なれば、異なるShapeとなる
- 先行して実装していたTruffleRubyの事例はRubyKaigi Takeout 2021のKeynoteで発表された
- CRubyへの導入はRubyKaigi 2022の発表が詳しい
- ちゃんと調べておきたい(2024/5/11)
- Rubyオブジェクトの構造(Shape)をキャッシュすることで、インスタンス変数等へのアクセスを高速化する最適化
- RFC 8305 - Happy Eyeballs Version 2: Better Connectivity Using Concurrency
- しおいさんの発表に関係ありそう
- v4/v6 dual-stackな環境での名前解決の遅延を減らすための規格のようだ
- Feature #20205: Enable
frozen_string_literal
by default- 実はfrozen_string_literalのデフォルト化が決定している
- 個人的にはちょっと寂しい
- YARVアーキテクチャ
- YARVの開発者であるささださんのページ。YARVの設計や命令セットが掲載されている
- めもりーさんの発表に関係あるかも(わからない)
- Property Based Testing
- ohbaryeさんの発表に関係がありそう
- 有名な実装にHaskellのQuickCheckがある
- 元ネタの論文 QuickCheck: a lightweight tool for random testing of Haskell programs (ICFP '00)
CRubyの開発を追う
- Ruby開発者会議の議事録
- https://github.com/ruby/dev-meeting-log/tree/master/2024
- 開発者会議 = CRuby開発者(コミッター)の議論の場、らしい。月イチ開催
- bugs.ruby-lang.org で議題が集められているようだ
- 例年RubyKaigi Day 0にオフライン版が開催されている
- bugs.ruby-lang.orgの購読
- ruby-coreを購読することで、bugsの更新のメールが来るようになる