DIGGLE開発者ブログ

予実管理クラウドDIGGLEのプロダクトチームが、技術や製品開発について発信します

RubyKaigi2024 に参加しました

DIGGLEは、2023年に続いて2024年も継続してRubyKaigiスポンサーを努めました。5/15〜5/18に沖縄で開催されたRubyKaigi2024にnikuが参加したので、その際の感想を公開します。

RubyKaigiの発表は「Ruby自体をよくする、Rubyの適応領域を既存から押し広げてゆく」という観点で捉えると私にはすっきりとまとめられるものが多いように感じました。全部面白かったのでどの感想コメントにも「面白かったです」というのがついていると思ってください。 (参加していなかった時間帯もあります)

1日目(5/15)

Writing Weird Code - RubyKaigi 2024

Weirdなコードを書くのは当人は楽しくやっていると思いますが、Rubyのコードってどこまで無茶なことできるの、変わったことできるのという探求は、Rubyのコードの(読み手からみた)整合性や一貫性に大きく影響すると感じました。Weirdなコードを書くときに、普通に書いてからWeirdな形に変えていくの、知らなかったなあ。言われてみれば、なるほどという感じですね。

Unlocking Potential of Property Based Testing with Ractor - RubyKaigi 2024

このトークはタイトルからはRubyを使ったライブラリを作った話という捉え方にもなりそうですが、IOではなくCPUがボトルネックになりやすいPropertyBasedTesting(PBT)をRactorを使うとどうなるか、現在のRactorの現実的なユースケースでの性能評価をするというのが目的に含まれていて、単なるライブラリを作った話ではありませんでした。着想が素敵ですね。もう一点、多くの言語ではExampleBasedTestingが最初にあり、PBTやFuzzingはここから認知されていくという感じだと思います。(Go言語はFuzzingを標準ライブラリとして組み込んでいますね)。PBTは考え方に慣れればそれほど大変ではなく書け、役に立ち、かつメンテナンスコストも現実的かなと思うので、Rubyでもこれから使われていくとどうなるのかなという点で私も興味がありますし、こういった品質担保のやり方が普通なコミュニティとなることでRubyの適用領域がさらに広がっていくといいですね。

Strings! Interpolation, Optimisation & Bugs - RubyKaigi 2024

"#{foo}#{bar}"のような文字列補完を実行するときの処理を8行消すことで、場合によっては2倍速くなる変更を加えたお話でした。Stringは文字列のサイズ(長さ)によって収める領域が異なります。過去にコミットされていた文字列補完最適化の処理が誤っていたので、収める領域が変わるときは遅くなっていた。またその文字列補完最適化は過去は速かったが現在は意義の薄いものだった。といったように複数にこみいった事情をかかえた状況で、最終的には単にその最適化ルートを取り去ることで速くなったそうです。結果は簡単ですが、こういった状況の見つけかた、調査、対処のアプローチといったプロセスが丁寧に解説されていて門外漢にもわかりやすかったです。ObjectSpaceってこうやって使うんだあ。

irb
irb(main):001> require 'objspace'
=> true
irb(main):002> my_str = 'hello'
=> "hello"
irb(main):003> puts ObjectSpace.dump(my_str)
{"address":"0x12035a1f8", "type":"STRING", "shape_id":0, "slot_size":40, "class":"0x10296ec60", "embedded":true, "bytesize":5, "value":"hello", "encoding":"UTF-8", "coderange":"7bit", "memsize":40, "flags":{"wb_protected":true, "old":true, "uncollectible":true, "marked":true}}
=> nil

The depths of profiling Ruby - RubyKaigi 2024

新しくpf2というプロファイラを作った理由と、どのように取り組んだかというお話でした。素朴なプロファイラでは得られない、Rubyの複数Thread動作の記録、C言語のスタックトレースとRuby言語のスタックトレースを並べて記録できるなどが特徴です。プロファイラは観察対象より下の層の情報も集める必要があるということをおっしゃっていて、なるほど確かにそうだが、作るのも大変だし、作ったあと観察対象の(内部構造が変わる)Ruby最新版に追従し続けるのも大変そうだなという気持ちになりました。使うときは今以上に感謝の気持ちをもって利用します。

Vernier: A next generation profiler for CRuby - RubyKaigi 2024

こちらもプロファイラのお話でした。機能としてはpf2とも重なっている部分が多く、Rubyの複数Thread動作の記録やGCでの時間停止、待ち受け時間(idletime)などを記録できます。時間帯が連続しているのはおもしろいですね。どちらの実装でも情報を集める役の(プロファイラ専用の)スレッドはGVLを避けるためC言語側で作っている、結果をビジュアルで見るにはFirefoxProfilerを使っているなど、複数のプロファイラ作りの視点から得られる、いろんな人が試行錯誤した結果今はこれが王道なのかなというものの見方が得られたのがおもしろかったです。今回のRubyKaigiではあともう一つRubyのプロファイラのお話がありました。三人が並んで親交を深めている写真が素敵でした。

Ractor Enhancements, 2024 - RubyKaigi 2024

Rubyの並列処理をいい感じにするRactorの現時点での状況と、今後のお話でした。Ractorの制限によりRubyコードで使うrequireやtimeoutに対応できないところを解決する試み、GCに時間がかかるのを解決する、メモリ管理の改善を挙げられていました。Ractorをよくするのと既存コードをRactor向けにしていくのを進めていくと、どこかのタイミングで違和感少なく特別な心構えなしに使えるようになると嬉しいですね。引き続き応援しています。RubyKaigiで話題になっていたネームスペースがうまくRubyに入ったらRactorはそれぞれ独立したネームスペースで動きますという形にするとRactor同士のメッセージングは難しくなりますがrequireの問題やsharingobjectの問題などの多くが解決しないかなあと妄想しました。

2日目(5/16)

Finding Memory Leaks in the Ruby Ecosystem - RubyKaigi 2024

Rubyのメモリーリークを発見するためのアプローチと、その結果たくさんのメモリーリークを発見して実際に改善できたというお話でした。一般にメモリーリークの発見に使われるValgrindというツールがあるのですが、Rubyに対して適用すると(機械的に見ると)メモリーリークの可能性があるけれど実際には問題ない処理が多量に列挙されてしまうためあまり役立たなかったそうです。そこでRuby3.3からRUBY_FREE_AT_EXITという環境変数を有効化するとValgrindから見てもメモリーリークに見えなくなる処理を足したそうです。そうするとValgrindで列挙されるメモリーリークの可能性は、本当にメモリーリークの可能性のあるものだけに絞られます。実際にこれを使ってたくさんのメモリーリークの発見に役立っているそうです。発想がすばらしいですね!

Optimizing Ruby: Building an Always-On Production Profiler - RubyKaigi 2024

常に本番環境でプロファイラをオンにしておく話です。プロファイラはプログラムの内部状況を取得するオーバーヘッドがあるため、プロファイラを使っているときはプロファイラを使っていないときに比べて処理能力が落ちてしまいます。ですから本番環境で常にプロファイラをオンにしておくというのは難しく、そんな夢のような話があるんだろうかと発表を聞く前は思っていました。発表者はDatadogにお勤めの方で、Datadogへデータを送るのに有用なddtraceという本番環境で常にプロファイラをオンにしても大きく支障ないgemを紹介してくれました。ちなみに本番環境でプロファイラを常にオンにするための秘訣は、データの一部のみを抜きだす(けれど全体像が掴めるようにする)サンプリングでした。ddtraceを使っていればDatadogにデータを送らずともローカルでも使えることをスライドの紹介で知りました。手元で様子をみるのに便利ですね。 https://docs.google.com/presentation/d/1hKiEQvqzuzkXDxhDiH36nc2Eew80_QYBSLp2vaXWurU/edit#slide=id.g1f7f8fc8955_0_313

class ExportToFile
  def export(flush) = !!File.write("hello-profiler.pprof.lz4", flush.pprof_data)
end
Datadog.configure { |c| c.profiling.exporter.transport = ExportToFile.new }
$ bundle add ddtrace && bundle install
$ DD_PROFILING_ENABLED=true bundle exec ddprofrb exec ruby hello-profiler.rb
$ lz4 -d hello-profiler.pprof.lz4
$ go tool pprof -http :8987 hello-profiler.pprof

Unlock The Universal Parsers: A New PicoRuby Compiler - RubyKaigi 2024

PicoRubyという、mruby互換の軽量なRuby実装があります。そちらをコンパイルするにあたって従来のパーサー、Lramaから生成されたパーサー、Prismの3つの候補が選択肢にある中、どれが向いているのかを比較していました。Lrama由来の場合はコンパイル時のメモリ消費やコンパイル結果のファイルサイズが他のものに比べて大きすぎたのですが、CRubyでは使うけれどPicoRubyでは使わない部分が取り外せず含まれているためで、それを外せるようにしてPicoRubyでも実用に近づけたよという話でした。馴染みのない分野だったのですが説明や図がわかりやすく、状況と問題がつかめたのでどうやって解決しているのかなというのをワクワクしながら聞けました。ちなみにPrismのほうは既にかなり完成されていてPicoRuby実用においても問題は少ないようでした。私の誤解があるかもしれませんが、そこからパーサーという領域では重なっているLramaとPrismのRubyKaigi2024時点での成熟度というのを感じとりました。あくまでRubyKaigi2024時点の話で、今後についてはわかっていません。引き続き楽しみですね。

Squeezing Unicode Names into Ruby Regular Expressions - RubyKaigi 2024

Unicodeにはcharacterpropertiesという、文字の種別が定義されています。たとえば「ひらがな」という種別は\p{Hiragana}で表わすことができます。次のように、既存のRubyでも正規表現で多くのものが使えるようになっています。

#2文字目に「に」が含まれている
'Юに코δ'=~/\p{Hiragana}/
=>1

こういったpropertyは既に大量にあり、またユニコードのバージョンが上がるごとに増え続けています。これをRubyの正規表現の中で扱うには、propertyの定義をRubyプログラムの中にデータ構造として持たなければいけません。単純に保持するのでは、データ量が多くなったり、該当の名前を検索する速度が遅くなります。うまく収めるためにRadixtreeという方式をとったというお話でした。大きいデータを、データの特性に着目してコンパクトにかつ使いやすいように収納していくさまを目にする知的興奮がありました。格好よかった。

3日目(5/17)

Turning CDN edge into a Rack web server with ruby.wasm - RubyKaigi 2024

RubyのWebフレームワークであるところのSinatraで作られたアプリケーションは通常PumaやApacheやNginxといったサーバーの上で動きます。アプリケーションとサーバーの間にはRackと呼ばれるミドルウェアがいて、サーバーの種類毎の違いを吸収した統一されたインターフェースを提供してくれています。そのおかげで、アプリケーションに変更を加えずにサーバーの種類を入れ替えることも可能になっています。今回はCDNEdgeでwasmが動くことと、Rubyがwasm化したことの2つを利用して、RackというミドルウェアがCDNEdgeをサーバーとして扱えるようにしてみよう。それが可能だとすると、アプリケーションの変更を行わなくてもCDNEdgeでコンテンツが配信できるという挑戦のお話でした。説明も平易で伝わりやすく、取り組みは簡単ではなかったのだなとわかりました。実際にCDNEdge上でSinatraアプリケーションが動いているのを見せるデモは説得力がありました。

Speeding up Instance Variables with Red-Black Trees - RubyKaigi 2024

Ruby3.2からはObjectShapeというパフォーマンス最適化方式が導入されています。これによりキャッシュしたインスタンス変数を速く読み取れるようになりました。一方でキャッシュしていないインスタンス変数へのアクセス速度に対しては素朴な実装のままでした。Ruby3.3ではキャッシュしていないインスタンス変数へのアクセスを速くするためにデータ構造として赤黒木を導入したそうです。実際にキャッシュミスのときの速度がRuby3.2より上がっていました。すごい。OkasakiStyleという論文の形式で赤黒木を実装したそうで、その論文のなかに「有能なプログラマなら15分未満で実装できる」と書かれていて実装のときに緊張したというくだりが好きです。

ERB, ancient and future - RubyKaigi 2024

RubyのテンプレートエンジンERBの歴史と、25年経った今そのときの判断が概ね正しかったというふりかえり、2012年には試したけれどできなかったRails互換のERBが最近思いついてできるようになりそうだという話でした。25年何かについて考えたり、10年くらい前にできなかったことを思い出して改めて挑戦してみるというのはその年数のあいだ生きていないといけないわけで、素敵だし、すごいことだなと感じました。歴史がある。

The state of Ruby dev tooling - RubyKaigi 2024

Rubyを使った開発で利用するツールの状況や提言のお話でした。Rubyの開発ツールは、選択肢が多く、多様性が高いとは言えるものの、初心者にはどのツールが適していてどれを入れると始めやすいか悩む原因ともなっているということをRustとの比較で示してくれました。発表者はこの状況をfragmentation(断片化)という表現をつかって説明していました。最近だとLanguageServerが開発ツールのハブになりつつあるので、ここをきっかけに状況を改善できるのではないかとお話してくれました。私も統合されたツールを持つ言語として挙げられていたGoやRustでの開発経験はよかったなと感じているので、一定うなずけるところがありました。ただ、めいめいが頑張って作りメンテしていたものを絞りこんで初期設定おすすめを選んでいくのは思い入れや歴史があり困難な道程になりそうだとも感じています。そうなれば、特に開発を始める人にとって便利なのは間違いないと思うんですけれどもね。うまくいくよう応援したいです。

Matz Keynote - RubyKaigi 2024

Matzのキーノートが最終日にあるのは珍しいですね。Ruby4についての言及もあり刺激的な内容でした。パフォーマンスがよくなって文句を言う人はだれもいない、そのとおりだなと思いました。DIGGLEプロダクトもパフォーマンスを上げ続けていますが、まだまだ速くできるところがあるので、新しい機能の導入とパフォーマンス両方をおいかけていきたいです。