Rubyにパッチを投げてきたアレコレ

はじめに

この記事は俺GW頑張ったというGWアドベントカレンダーの5月1日の記事です。

プログラミング言語Rubyにテストの修正やbuiltin対応などでパッチを投げてきた時の知見などを振りかえってみたかったので書いてみた。

やったこと

テスト修正関連

そもそもRubyのパッチとかを書き始めたのは、ruby-jpでコミッターの方が「テストの修正をしたいんですが、手伝っていただける人いませんか?」と投げられてたのがきっかけ。

具体的に修正したテストはこれら

remove warning & support multi-run test for test/psych/visitors/test_… #2881

remove warning & support multi-run test for test/psych_test_yaml.rb #2887

Fix remove warning & support multi-run test for test/psych/visitors/test_to_ruby.rb #2893

support multi-run test for test/did_you_mean/test_verbose_formatter.rb #2894

support multi-run test for test/webrick/test_filehandler.rb #2896

support multi-run test for test_readline.rb #2914

support multi-run test for test/did_you_mean/spell_checking/test_class_name_check.rb #2880

Rubyではmake test-allというすべてのテストを行うコマンドがあり、それをmake test-all TESTS=--repeat-count=2のように繰り返して実行するといくつかのテストが落ちてしまうという問題が起きていました。

原因としては、変数などの初期化がされていないので二回目以降に落ちるということが多かったですね。 とはいえ、原因の判別は結構難しかった……。

テストの修正を行うにあたってまずは落ちているテストのリストアップを行いました。 この時、注意したのは自分の環境要因で落ちているものもあった点ですね

たとえばWSL(Ubuntu 18.04)を使用した環境ではネットワーク関係やIO周りのテストで落ちることがありましたが、VM(Ubuntu 18.04)上では落ちることがありませんでした。 このように環境によってテストの結果が変わるので、そこを分離していくことから始めました。

結果的にWSL上でのテスト環境はネットワークやIO周りの問題が解決しなかったので、おとなしくVMを使って作業することに。

そこから落ちているテストをピックアップしていき、落ちている原因らしきものをチェックしていきました。

チェックにあたっては、最小の構成でテストが落ちるコードを書いて動きを確認。その後に、原因らしき箇所を洗うという流れで進めました おおよその場合は同じテストファイルの中で初期化が済んでいないということが原因であり、それらは比較的対処が楽でしたね。

辛かったのは、別のテストで値が変更されておりテストが落ちるケースでした……。 こういうテストが落ちる箇所は再現コードを作るのが難しく、なんどもRubyリファレンスマニュアルを読みふけり、Rubyの実装を読んでました。

こんな感じでテスト関係は修正を進め、無事テストが通るようになりました。

builtin対応

builtinというRubyとCを使ってRubyのメソッドを実装できる仕組みがあります。 builtinを使うことでキーワード引数を使ったメソッドはHashを作らないため高速に動作するようになります。

詳しくはこちらを参考に

Ruby(とC)でRubyを実装してみた(builtinで遊んでみた)

そのbuiltin対応をパッチとして投げました。

support builtin for Kernel#clone #2954

support builtin for Kernel#Float #3048

Kernel#cloneKernel#Floatの実装をbuiltin対応させて処理を高速化できたのは結構うれしかったですね。 ただ、ベンチマークを追加し忘れていたりしたので、その点は反省点かも。

ちなみに、今もいくつかのメソッドのbuiltin対応を進めていますね(いくつかベンチマーク忘れてたりしたけど)。

support builtin for Numeric#clone #2968

support builtin for Dir class singleton method #3007

support builtin for String#lines & String#each_line #3022

support builtin for Exception#full_message #3038

support builtin for Kernel#Integer #3054

その他

ドキュメント周りやCIの修正、不要になった関数宣言の削除とかやったりしましたね。

Add array.rb to .document #2904

Fix AppVeyor CI sometimes fail #2979

Fix AppVeyor pull request CI #2983

remove unused rb_str_clear define #3059

この辺は、あんまり複雑なことはしていないですね。 ソースコード読んだりしてて気になったので修正投げた感じです。

CIは落ちてたので修正投げたんですが、挙動が良くわからないところもあり良い感じの修正にならなかったのが残念ですね。

今現在も、二つほどCのコードを変更したものを投げたりしてますね。

Add rb_ary_max_or_min func #3060

Move rb_big_isqrt defination to internal/bignum.h #3065

おわりに

振り返ってみると意外とアレコレ修正パッチ書いてるなぁという感じ。

今後も何かしら修正できそうなもの見つけたらパッチを投げていきたいと改めて思ったね。