ENECHANGE Developer Blog

ENECHANGE開発者ブログ

RubyKaigi 参加レポート(後半)by id:cuzic

ENECHANGE で働いている id:cuzic です。

前回の記事 は速報性を重視した結果、基調講演に関してのみの記事となってしまっていました。

基調講演以外にもとても良い発表ばかりでした。今回は一気に3日分、私が聴講したセッションについて紹介します。

1日目

Ruby 3 Progress Report by Matz & the Ruby Core Team

全体として、今回の RubyKaigi でどんな発表があるかの頭出し。

まだ、どのセッションを聞くのか決めていない人にとって役立つ内容でこういうのはとても良いと感じた。

こういう発表でまず概要を説明してもらえると、もっと深く知りたいと思って、結果的に Ruby に開発の最新状況について詳しくなることができる。

特に静的解析まわりで今回の RubyKaigi では多数の発表が用意されており、非常に注目されており、活発に進化している分野なのだな、と感じた。

Ruby 3 で導入されるパターンマッチングは是非つかいたいと思った。例が赤黒木(red black tree)をパターンマッチングで書くという話だったのだが、初見では正直むずかしかった。別に解説 を読んでそれから、:R が赤色、:B が黒色を意味しているということを理解できたので、ロジックを読み解くことができたが、:R ではなく :Red とかにしくれていたらもっと分かりやすかったかもしれない。

あと、わりと Ruby 3 でやるかも、ということのいくつかがやらないことになったという説明があった。列挙されている内容はわりと納得感があるものだったので、Ruby は良い方向に進んでいるという感覚を持てた。互換性を大切にすることは大事だと思う。

Numbered Parameter という @1 とかでブロック引数にアクセスできるようにする機能は、期待大。

あとは、目玉となる非互換性である、キーワード引数の変更の話。 私自身はキーワード引数はこれまでほぼ使ってこず、地雷を踏んで来なくて良かった。 キーワード引数の考え方がこれから整理される見込みのようで、そうなれば使ってみたい。

Performance improvement of Ruby 2.7 JIT in Real World by @k0kubun

MJIT といわれる Ruby の最適化・高速化の進捗報告的な発表。

発表内容と無関係だが、Optcarrot というファミコンエミュレータが天才(@mametterさん)が作ったからリアルワールドの例とは全然言えないという点を強調していたのがすごく面白かった。

MJIT のような最適化、高速化はとても期待している。発表の最後にあったように、RuboCop等で細かな最適化についてガミガミ言われるのはとても生産的でないと思う。そういうのはコンパイラが勝手にやってくれてしかるべきであるし、プログラマがいちいち気にすることではないという考え方に強く賛同する。

Write a Ruby interpreter in Ruby for Ruby 3 by Koichi Sasada

Ruby 3 に向けて、Ruby で書いた方がいいところはRubyで書いていこうという発表。

以前の RubyKaigi で @k0kubun さんが指摘していたことを実現する話。現在 C 言語で書いていたところを Ruby で書き直すと Ruby はずっと速くすることできるというのの具体的なことが分かって良かった。

当時は、具体的なところがよく分からなかったが、今回の笹田さんの発表を聞いて、とても腑に落ちた。C メソッドでは情報が抜け落ちていたり、例外処理やキーワード引数は Ruby で書く方が速いというのを丁寧に説明してもらえたことで、深く理解できた。

そもそもの話としては、ささださんは別に Guild という並列処理の機構を新規に導入しようとしていて、それに向けてコンテキストを引数として追加するために API の変更をやろうとしている。それに合わせて、Ruby での再実装をやっているという流れのよう。

Ruby で再実装するために FFI記法を新たに導入したり、VM 命令を追加したり、さまざまな最適化のテクニックを導入したりでパフォーマンス面を含めて実用的なレベルにしたよ、という話でした。

メンテナンス性も向上して、将来の並列化の実装にもつながるということで、とても良い未来につながる内容だな、と思いました。

A Type level Ruby Interpreter for Testing and Understanding by @mametter

Ruby 3 の静的解析に関する発表。

今回は、静的解析の発表がとても多いのですが、特に、型を書かなくても(型注釈がなくても)、適用可能な静的型解析器である「型プロファイラ」の話。

印象としては、これはすごく良いものだと思ったけど、実用レベルで完成させるにはとてもこれから長い努力が必要そうに思った。

Fibers Are the Right Solution by Samuel Williams

マルチプロセスではなく、マルチスレッドでもなく、ブロッキングI/O の処理には Fiber が最適という話。

とても期待していて、聴いていたのだが、感想としては「うーん。」というかんじ。

マルチプロセスやマルチスレッドの問題点に関する指摘はまぁそうだよね、と納得できるところがとてもあったんだけれども、Fiber で解決できるという説明のところで、「いやいやそれでできることはみんな分かっているけど、それが面倒だからやらないんでしょ」という気持ちになった。

AutoFiber 的なことをもっと簡単にできるようなフレームワークを紹介してくれるのかな?という期待値を持っていたのが間違いだったのかもしれない。

私の理解等に間違いがあれば、指摘してください。

Compacting GC for MRI v2

スーパーざっくり言うと、compacting GC を実用レベルにした、という発表。

高速化にはキャッシュヒット率を高めることが大事。 → キャッシュヒット率を高めるには、使っているメモリ領域と使っていないメモリ領域がくっきり明確に分かれている方が有利 →GC を繰り返してくると、歯抜けにメモリが使われちゃうからこれを整理しなおそう!というのが GC コンパクション →分かりやすい例で言うと Windows のデフラグ

→ほかにも Unicorn のような fork するときにメモリ領域を Copy on Write するようなケースでも compacting GC しておくと有用。

ただし、実用レベルではいろいろあったので、ちゃんと compacting GC できるように頑張りました、という発表。特に Ruby の Object#object_id はメモリ上の位置、アドレスそのものなので、メモリ上の位置を動かしたらいろいろマズいことが起きる。なので pin 止めして動かさないようにするとか、細かい工夫について、聞きながらとても大変そうだな、と思った。

とはいえ、2年前に聞いたとき、まだまだ Future Work がたくさんあって大変そうだな、と思ったけれど、今回聞いてみたらかなり完成に近づいている実用レベルになっているという印象で、Aaron さんすごいな、と思った。

2日目

All bugfixes are incompatibilities by @nagachika

いろんな修正をバックポートする中での失敗について。

パフォーマンス改善をバックポートするな、とか教訓がいろいろと語られました。

"Known bug" can be better than "Regression"

なんていうのはどのプロジェクトでも当てはまることだな、と思いました。

自分で過激派ということを強調していたものの、実際には失敗を避けるためにかなり工夫し、反省しているという点がとても印象に残りました。

Six Years of Ruby Performance History by Noah Gibbs

いろんなベンチマークと、Ruby や Ruby on Rails のパフォーマンスの改善の歴史についての発表。

全体的に、ベンチマークではどういう点を気にするべきかという点において、参考になりました。

ミクロに計測する(特定部分にフォーカスする)のか、 マクロに計測する(全体的なパォーマンス計測する)のか、

レイテンシ(応答の待ち時間)を計測するのか、 スループット(単位時間にどれだけ処理できるか)を計測するのか

Ruby や Ruby on Rails に特化していないパフォーマンス全般に関する話も多く、自分でパフォーマンス改善に取り組む場合でも参考にできそうなことが多くありました。

Ovto: Frontend web framework for Rubyists by @yhara

Hyperapp という 1kB と非常にコンパクトなサイズで実現した React 的な View フレームワークを参考にして、Opal という JavaScript の代わりにフロントエンドを Ruby で記述できる言語の上で、Ovto というフレームワークを構築した話。

本題とは関係ないが DIY プログラミング(自給自足プログラミング)という考え方がとても共感できた。

ハッシュで状態を持つのではなく Ovto::State というクラスを導入するにいたった設計思想について丁寧に説明があったのが良かった。クラスにすることで、 state['pagee'] のような typo の場合に nil を返すのではなくよりデバッグしやすくすることができるというコダワリ。

また、State と Action と Component の3つのクラスに集約しているのも大クラス主義なかんじがして、とても学びやすく設計されていると感じた。

かなりシンプルなコードで、アプリ制作が可能そう。一度使ってみたい。

State of Sorbet: A Type Checker for Ruby

Sorbetという Ruby の型チェッカーに関する発表。

Stripe という決済系アプリケーションを Ruby で開発しているのはそれだけでかなりすごいな、と感じた。

マイクロサービス化しているけど、単一repoという Stripe の設計は面白いな、と思った。あまり発表の中で言及はなかったけど、たしかに repoの分割等をすると、分割前の修正を追うことができなくて、不便だったりするし、現在ではストレージの制約などはなくなってきているので、単純に単一 repoで運用するという決断もあるのかもしれない、と思った。

本題についてだが、単に作っただけではなく、実際に Stripe という大規模アプリケーション開発の現場で使っているのはとても興味深いと思った。

Sorbet を使うと、VSCode に対応して、ほかの言語でできているように、コードを書いている途中で typo を指摘してくれたり、メソッド定義にジャンプできたり、autocomplete できるようになるようで、とても便利!

ぜひ使ってみたい。

Stripe は RubyKaigi でブースを出していて、発表者と直接質疑などすることができた点もとても好印象でした。

A light weight JIT compiler project for CRuby by Vladimir Makarov

MIR という中間コードを導入することで、CRuby MJIT では2階層のコンパイルが必要だったのを 1階層の軽量なコンパイラで済むようになるよ、という話。

コンパイル速度で 100倍速く!スタートアップ時間で 100倍速く!コードサイズは100倍小さく!というのがとてつもなく印象に残った。目標が高すぎ。

Red Hat に勤務して、 GCC の最適化の研究をずっとやってきた Vladimir Makarov さんでないとそんな高い目標を掲げられないでしょ・・・と思った。

What is Domain Specific Language? @tanaka_akr

どういう条件を満たせば、DSL なのか、という話。

Rake を例にして、前処理、後処理の記述を省略できるようにしたり、filesh のように短い記述を可能にしたりすることで DSL になっているという話はとても納得感があった。また、Rake は Make と同じセマンティクスに基づいていて、ビルドツールに関するドメイン知識のある人にとって習得しやすくなるというのは、そのとおりだと思った。akr さん作の open-uri でも感じることであるが、人がすでに習熟しているもの、セマンティクスに似せて作ることで学習コストを下げるという考え方は自分自身これからも意識していきたい。

ERB で << を内部的に使っていたり、.freeze を使って高速化しているという実装の詳細を隠すという役割が DSL にはあるという指摘にはハッとした。たしかにそのとおりなのであるが、言われないと気が付かない。

最後にどの程度 DSL を使うべきかという議論で only one dirty technique is enough という指摘。

実際、そういう dirty な技術を使わずとも実現できることは多いので、私の実感にも合っていると感じた。

Lightning Talks

いろいろと面白い発表があったが、力尽きていたので、スキップ。

3日目

Ruby Committers vs the World

Numbered Parameters の議論がわりと活発に行われていた。

3.times do puts @1; end みたいにブロック引数を受け取れるような新しい文法。議論になったのは @1 の部分をどうするか、という点。

個人的には新しい文法を導入しなくても it のようなメソッドが Kernel にあればいいと思ったけど、どうなんだろう。それか $_ とかをこの目的にも使うか。

あと、Matz から メソッド呼び出しするときに .ではなくもっと優先順位が低い演算子があったらいいのではという話で盛り上がった。Elixir の |> みたいな。

本当は $$ とか使えればいいんだけど、みんな知っているように $$ はすでにプロセスID(Process.#pid)として使ってしまっているから使えない。

右代入も毎回議論になるけど、なかなか良い記法がなくて話が進まない。

右代入は右矢印に見えるようにしたいというので、決まらない。=>-> もすでに使ってしまっている。私の個人的な意見としては右代入は => にしてハッシュとしての使い方と衝突しないように使える状況をかなり制限したらいいと思ったりするんだけど、左代入は使えるけど、右代入が使えない箇所があると、マズいから採用されないのかな。

The Selfish Programmer

今回、私が聴講した中で、一番エモい発表だった。

この発表者の作の todo_or_die がほんの少しだけ紹介されて。「この発想はなかった!」的なかんじで面白かった。

wanikani というアプリが紹介されていて、wanikani の作者なのかと思ったけど、そういうわけではなく、wanikani を勉強するタイミングを notify する whenkani というプロダクトの作者だったよう。

この発表とはまったく関係ないが、単語のスペルと発音と意味の3つ組をいろんな組合せで勉強したいというニーズはけっこうある。wanikani は日本語のローマ字、ひらがな、英語の意味の3つ組でミニテストを試せるようにできているが、ほかの言語でもできるようになっていたら便利だな、と思った。

The challenges behind Ruby type checking by @soutaro

Ruby 3 のメイン機能の1つ、Type Checking を実現する Steep に関する発表。

こういう仕組みができて、どのメソッドがどういう引数をとることができるかということが明確になるととても良いと思った。特に Ruby on Rails のメソッド群とかは何がとれるのかが明確でないことが多い。こういう引数の型に関する情報が簡単に得られれば開発生産性も上がりそうだ。

Performance Optimization Techniques of MessagePack-Ruby by Sadayuki Furuhashi

Ruby でのメッセージパックの最適化技法に関する発表。

浅学ながら、

s = "a" * 1_000_100
10_000.times do
  s.slice(100, 1_000_100)
end

s = "a" * 1_000_100
10_000.times do
  s.slice(100, 1_000_100 - 1)
end

と比較して、ずっと速いというのは知らなかった。最後の文字が含まれれば Copy on Write が自動的に行われるため、文字列のコピーを作成する必要がなく、ずっと速く作れるということ。しかもこれは SHARABLE_MIDDLE_STRING flag をセットすることで、制御できるそう。

一方、Ruby において、 (2 ** 62) - 1 が即値(immediate value) なのでオブジェクト生成が高速だが、 (2 ** 62) はヒープ上にオブジェクトが作られるため、低速になるというのは知っていた。知っていることが発表の中で出てくるとちょっとうれしい。

Play with local vars by @ujm

@ujm から出題された下記の問題はなんか朝、 @ujm とばったり会ったときに出された問題だった。私はちゃんと正解を回答できたのだけど、そしたら人類で最初に正答できたとのことで褒められた。とはいえ、私は最初文法エラーになると思って @ujm に助け舟を出されて正答できたのだし、下記がなぜ文法エラーにならないかは説明できなかったので、ちゃんと正答できたという実感はない。

require 'continuation'
def foo(x = (return callcc {|c| return c }; x))
  'ruby'
end
p foo['vim']

上記が文法エラーにならない理由は、; x に秘密があって、これがあることで右辺値として文法的に正しいとみなされるらしい。

本題。全体としては Ruby のローカル変数に関する話。

正直、実用レベルという意味で今回の発表が参考になるようなコーナーケースに実際のコーディングの現場で直面することはないだろう。しかしながら、この発表の中で取り上げられている Ruby がどのように動作しているのかという裏側の機構に関する知識自体はとても役立つものであると感じた。

@ujm の場合は、vim という圧倒的な得意分野があるので、それを活かして、vim の超絶技法を活かした live coding を使った発表をしていた。わずかな type 数ですごい量のコードを高速に生成していた。これは自分の得意分野をどのように発表に活かすかという点で戦略的で効果的にできていた。

また、今回の発表はタイトルに Play というのがあるとおり、いろいろと実際に手を動かしてハックすることによって、そこで何が起きているのかについて詳細を理解するという手法をとっていた。私自身、テキストをどんなに繰り返し読んでも身につかないことがたくさんあると実感している。深いところまで理解するためには自分の手を動かさないといけない。自分の手を動かすことが深遠な原理・一般則を素早く習得するための近道であり、自分自身ももっと真似していかないといけないな、と感じた。

Red Chainer and Cumo: Practical Deep Learning in Ruby

Ruby でデータサイエンスをするためのライブラリである Red Chainer と Cumo に関する発表。

この発表はもっとちゃんと聞きたかったのだが、このタイミングでブースをいろいろと回っていて、特に転職DRAFT の使い方についてヒアリングしていたため、十分に聞くことはできなかった。

そのため、この発表で触れられていたかどうかは分からないが、Ruby でのデータサイエンスの需要は大いにあると思っている。もちろん、Python の方がいろいろと優れている点があることは承知している。しかしながら Real World Application はデータサイエンスだけでは完結しない。データのクレンジングや加工といったログに関するテキスト処理、またそれを表示するための Web Application の開発なども必要になってくる。それらの関連タスクを Ruby で実施したいので、データサイエンスの部分も含めて Ruby で書くという判断は十分にありえると思っている。

今回の発表でのライブラリ群にはとても期待しているし、ウォッチしていきたい。

Optimization Techniques Used by the Benchmark Winners

最後の発表ということもあり、疲れていてあまり覚えていない。

ほか、関連イベント等について

特に3日目において、下記のことが印象的だった。

クックパッドでの Ruby クイズ

1時間ほど解くのに時間がかかってしまっていたので、まったく期待していなかったのだが、3日目の3番目の問題について、正答できたということで、表彰してもらえた。

Hint に書かれていることがとても良いヒントになっている良問が多かった。(といいつつ、私が表彰された問題は No Hint だったのだが)

ある意味、@mametter さんが出題者であるということが最大のヒントだったのかもしれない。

スポンサーブースを巡回し、スタンプラリー

私はかなり遅れてスポンサーブースの巡回するスタンプラリーを3日目にやっていた。印象的だったのを2つだけ。

転職Draft

最近、ENECHANGE ではとてもエンジニア採用を積極化しています。特に転職Draft というサービスの利用には力を入れています。利用開始の初期の段階であるので、いろいろとノウハウ等についてみっちりヒアリングしました。

特に、自己推薦という機能についてはあまり知らなかったので、教えてもらえてとてもためになりましたし、メッセージの文章についても具体的なフィードバックを受け取ることができ、役立ちました。

リンクアンドモチベーション

3日目のキーノートの発表の前に、リンクアンドモチベーションの執行役員の麻野さんからのスポンサーセッションがあった。実は麻野さんは私の高校の同級生であり、旧知の仲。

そういう経緯もあり、そのスポンサーセッションの直前にリンクアンドモチベーションのブースに立ち寄るとふつうに麻野さんが座っており、まとまった時間お話することができた。リンクアンドモチベーションの麻野さんといえば、いろいろなイベントなどで引っ張りだこの有名人。共通の知人の近況なども知ることができ、良かった。

全体をとおして

RubyKaigi はとてもいいイベントでした!

また、ぜひ参加したいですね。