最近のRubyコアの動向: 2022年3月版(翻訳)
Rubyコア内部の最近の開発状況を把握する時間の余裕があるRuby開発者は多くありません。そこで、Ruby Bug trackerで行われている最近の開発状況をまとめてみることにしました。ここでは機能提案のみをまとめることとし、バグのチケットは対象外としますが、重要なバグチケットが発生した場合は記事の末尾で言及することにします。
今回は、2022年3月に議論された最も重要なissueを紹介します。
🔗 ドキュメント: 複数のハッシュ値の結合方法を改善
#18611(現在オープン)では、ドキュメントの改善がChris Seatonから提案されました。この改善は、開発者が複数の値を結合してハッシュコードを作成するときの正しい方向を示せるようにします。
どんなときにハッシュ値の結合が必要か
Hash
のキーでカスタムクラスを使えるようにしたい場合は、カスタムの#hash
メソッドを実装する必要があります。このメソッドは、接続された値を正しいバケット(bucket)に入れる必要が生じたときにVMから呼び出されます。
この機能で解決される問題
多くの開発者がカスタムの#hash
メソッドを不十分な方法で使っています。これではハッシュテーブルの衝突が無駄に発生してパフォーマンスが低下してしまいます。
承認された適切な方法を使うことで、開発者がこのメソッドを実装するときに正しい方向に導かれるようになります。この方法はほとんどの場合とても簡単です。
class MyCustomClas
def initialize(attrs)
@x = attrs[:x]
@y = attrs[:y]
end
def hash
[@x, @y].hash
end
end
また、このベストプラクティスをVM内でもっと最適化すればパフォーマンスがさらに向上するという提案も出されています。
CRubyにWASIベースのWebAssemblyサポートがマージ
#18462(現在オープン)が提案されたのは割と前のことですが、最近になって実現されました(実は3月より前のことでしたが、私が以下のMedium記事を偶然見かけたのは最近のことでした)。
参考: An Update on WebAssembly/WASI Support in Ruby | by kateinoigakukun | Mar, 2022 | ITNEXT
特に問題がなければ、Ruby 3.2でWASIプラットフォームもサポートされる予定です。つまりRubyをブラウザの中で実行可能になるということです。さらに重要なのは、WASIイメージをデプロイしてエッジコンピューティングに利用することも、ちょっとしたスクリプトのデプロイに使うことも可能だという点です。WASIイメージにはRuby VMが含まれているので、スクリプトを実行するコンピュータにRubyがなくてもよいのです。既にRuby 3.2.0 Preview 1をダウンロードすればこの機能を試せるようになっています。
メソッドの不意な上書きを防ぐ
Ed Mangimellによる#18618(現在オープン)では、ライブラリを「利用する」開発者が既存のメソッドを上書きする新しいメソッドを作成したときに何らかの形で通知する方法の追加を提案しています。現時点では、このフィードバックはファイルが解析されるときに例外を発生する形にすべきという提案になっています。
主にこのアイデアに賛成する人からそこそこ反響を得ているものの、コアコミッターからのコメントはまだありません。また、Rubyだけでやれるソリューションもありそうなので、この提案がRubyに取り入れられるかどうかは今後を見守りたいと思います。
GCコンパクションの2つのカーソル移動順を入れ替える
訳注
週刊Railsウォッチ20220419もどうぞ。
Ruby 2.7では手動のGC(Garbage Collection)コンパクションが追加されました(#15626)が、#18619でこのアルゴリズムの変更が提案されています(現在はマージおよびクローズ)。
理由は2つあります。1つ目は、GC後に行われる現在のコンパクションでは、オブジェクトをサイズプール(size pool)間で移動するのが非常に困難であること。2つ目は、コンパクションで一部のサイズプールが取りこぼされることです。現在の進捗状況は以下をどうぞ。
- PR: Reverse the order of GC compaction cursor movement by eightbitraptor · Pull Request #5637 · ruby/ruby -- マージ済み
サイズプールについて
サイズプールは固定サイズのヒープで、サイズ次第では複数のオブジェクトを内包できます。現在のRubyには多くのサイズプールがあり、どのサイズプールもそれぞれ独自のヒープと「スキャン用カーソル」「コンパクト用カーソル」を持っているので、この問題が発生します。
IO#timeout
とIO#timeout=
がすべての(ノン)ブロッキング操作に導入
#18630(現在オープン)は主にFiberスケジューラに関連します。プルリク#5653(現在オープン)がマージされれば、すべてのノンブロッキングIOインスタンスがIOインスタンスごとのタイムアウトを備えるようになります。こうすることで、IO操作を呼び出すたびにタイムアウトを新たに作成してエラーハンドリングできるようになります。
Fiberスケジューラについて
Fiberスケジューラによって、自動切り替えのイベントループを書けるようになります。ノンブロッキングIOイベントが発生するとイベントループが別のFiberを実行し、その結果スループットが著しく増大します。Rubyのこの機能を活用したgemとしては、Fiberスケジューラと同じ作者によるasync gemが最も有名です。
可変幅アロケーション: 配列
#18634(現在はクローズ)の機能提案と#5660(現在マージ済み)のプルリクが上がっています。この機能強化はユーザーにすぐ影響するものではなく、長期的なRuby VM改善の一環です。最初の改良は、String
に可変幅アロケーションが実装されたときにマージ済みです。
可変幅アロケーションについて
現在、ほとんどの巨大オブジェクトはメモリ内のさまざまな場所にデータを分割して保存しています。これはCPUキャッシュがうまく効かなくなってパフォーマンスが大幅に悪化するという問題があります。可変幅アロケーションは、データをメモリ上のメタデータの直後に配置することでこの問題を解決します。これがほとんどのオブジェクトで行われるようになれば、パフォーマンスは大きく改善されます。詳しくは作者による以下の動画をどうぞ。
String#sub
とString#sub!
の引数をデフォルトで空文字列にする
#18640(現在オープン)ではsub
メソッドの変更が提案されています。作者はデフォルトの置き換え文字列を空文字列にしたい意向です。まだ反響は多くありませんが、今後の成り行きを見守りたいと思います。
Ripperの名前付きフィールド
#18642(現在オープン)は、Ruby向けツールを作成している人なら強く興味を惹かれるかもしれません。RipperはRubyスクリプトのパーサーで、コードに対応する配列を多数含んだ配列を返します。以下はきわめてシンプルな例です。
Ripper.sexp("puts 'wuhu')\
=> [:program,\
[[:command, [:@ident, "puts", [1, 0]], [:args_add_block, [[:string_literal, [:string_content, [:@tstring_content, "wuhu", [1, 6]]]]], false]]]]
しかしこれを扱うには、プログラム側で暗黙の知識が多数要求されます。提案者は、配列内で暗黙の意味が込められたインデックス番号を使う代わりに名前付きノード名を使うRipper::Tree
サブクラスを追加するプルリク#5679(現在オープン)を作成しました。
呼び出し可能なものをすべてProcに強制型変換する
ここ最近のRubyエコシステムでは関数型プログラミングに向かう傾向がありました。これはdry-rbエコシステムで多用されています。Rubyで関数型プログラミング的な方法を使いやすくするために、呼び出し可能な任意のオブジェクトをProc
に強制型変換する#18644(現在オープン)が提案されています。
メリットのひとつは、Proc
をカリー化可能にできることです。カリー化するということは、すべての引数を一度に1個の関数に渡す必要がなくなるということです。引数が足りない場合でもエラーを発生せずに残りの引数を受け取れる新しいProc
が生成され、すべての引数を渡せば結果が返されます。この手法を使えば、コンポジション可能なよいオブジェクトを書きやすくなることが期待できそうです。
prettyprintの強化
#18654(現在オープン)の記述が実に見事なので、ここでは手短にまとめます。prettyprintで使われるデータ構造には、このクラスをコードフォーマッタで使うための新機能があります。対応するプルリクは#3です(現在オープン)。
IO#wait_readable
とIO#wait_writable
をコアにマージ
#18655(現在オープン)もFiberスケジューラに関連します(Rubyコアの開発を追いかけていると、この方面が非常に活発であることが実感できます)。このissueは既に解決済みらしく、#5694(現在オープン)をRubyコアにマージしようという流れのようです。
次点: バグ編
FreeBSD 13のissue
最近RubyのCIがFreeBSD 13で落ちています。このプラットフォームのメンテナーは現在多忙なので、お手すきの方は#18613にてお声をおかけください。
原文お知らせ
- 私のブログをぜひメールでご購読ください。こちらのページで登録可能です。
- Mediumの使い心地が気に入りましたら、Mediumメンバーシップ登録のうえ、ぜひ私や他のブログライターを応援してください(5ドル/月、または50ドル/年のみ)。こちらのリンクから登録いただくと、費用の一部が私へのサポートに使われます。その他の費用は発生しません。登録いただいた方に深く感謝いたします。
概要
原著者の許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。見出しの階層は原文と異なるものもあります。