simanのブログ

ゆるふわプログラマー。競技プログラミングやってます。Ruby好き

RailsDM 2019 で登壇してきました

RailsDM 2019 で登壇

RailsDM 2019 で「Ruby のコード解析の「静」と「動」」というタイトルで発表してきました。

f:id:simanman:20190322183624j:plain:w800

去年の年末あたりに平野さんから登壇依頼が DM 経由で来て「せっかくの機会なのでやるか!」と思い引き受けることにしました。(CFP 形式だと登壇してなかったと思います)

RailsDM なので Rails に関する話が出来れば良かったですが、自分はあまり Rails をそこまで触ってなかったので 普段 Rails を使っている開発者が知らないことを発表するのは少し難しそうだなと思い、Rubyソースコード解析周りの話をしました。

静的解析、動的解析については過去にも色々発表があるのでそこまで新鮮味は無さそうな気もしましたが、2.6 の新機能の発表はまだ無さそうと思ったのでそのあたりを発表すればそのあたりは大丈夫かなという感じでした。

AbstractSyntaxTree とか TracePoint とか InstructionSequence の利用例を調べるためにローカルで https://github.com/akr/gem-codesearch の環境を整えて色々利用例を眺めてたのですが、結局時間の都合上あまり紹介することは出来ませんでした。(あとあまり調査が出来ていなかった)

発表に関しては正直 10人ぐらい来れば御の字だと考えていたので想像より多くの人に来ていただいて感謝です。ありがとうございました。

また、このような素敵なカンファレンスを開いていただいた RailsDM 運営スタッフの皆様ありがとうございました。

発表できなかった話題

以下は発表資料の中に入れてたけど時間を削るために省いた内容です。

RubyVM.resove_feature_path の不具合

RubyVM.resolve_feature_path ではパスを取得したいライブラリ名を読み込む前じゃないと動作しないという問題があります。(trunk では修正済み)

pp RubyVM.resolve_feature_path('prime')
require 'prime'
pp RubyVM.resolve_feature_path('prime')

実行結果

[:rb, "/Users/siman/.rbenv/versions/2.6.1/lib/ruby/2.6.0/prime.rb"]
[:rb, false]

なのでサンプルコードでさらっと 2.7 前提のコードを書いてましたが、そういう背景がありました。 あとこれはまだ確認はしてないのですが、 gem install 経由で入れたライブラリ名のパスについては取れない気がします。($LOAD_PATH で探して終わり)

iseq オブジェクトを自前で作成して差し替える

iseq を差し替える手法として別のファイルをコンパイルして差し替える方法を紹介しましたが、別の方法として iseq の命令列を作成してそれを Ruby の Cの関数を利用して読み込むという方法もあります。(こっちのほうが出来ることの柔軟性は高いと思います)

詳しくは下記の記事に乗っているので是非読んでみてください。

https://magazine.rubyist.net/articles/0053/0053-YarvManiacs.html

coverage

個人的に Ruby の coverage ライブラリは気になっていたので動的解析の部分で入れたかったのですが時間の都合上カットしました。2.5 で 分岐カバレッジ、 2.6 で oneshot カバレッジが利用できるので組み合わせたら色々出来そうな気がしますが、ネタが出てこなかったです。(なので動的解析部分が TracePoint だけになってしまいました。

標準ライブラリの使用例の調査方法

rubygems にあるような gem の場合は reverse_dependencies で調べることが出来るのですが、標準ライブラリはそれが出来ません。かといって GitHub の検索を使ってもあまりうまくいかないので、今回 gem-codesearch を利用しました。自分はセットアップに数日かかりました。

セットアップが終わったらあとは csearch [検索したい文字] で検索することが出来るようになります。

$ csearch RubyVM::InstructionSequence

今回作った gem

今回の発表準備の期間で作った gem です。

astree

自分は tree コマンドが好きなので色々 tree コマンド風に表示させることをしているのですが、今回はそれの AbstractSyntaxTree 版です。

ast2dot

AbstractSyntaxTree で得られた構文木を dot 言語で表現するやつ。発表資料の一部はこれで吐き出して少し編集したものを使いました。

ast_distance

2 つの構文木を受け取ってその編集距離を出すやつ。ただ AbstractSyntaxTree の場合は少しのコード変更でもかなり変わりやすいのでなかなか有効活用は難しいかもしれません。

load_tracer

ファイル間の依存を調べる gem。 2.7 でしか動かない。まだ実験的な実装なので得られる結果が正しくないこともあります。

懇親会

懇親会では色々な人と話すことが出来て楽しかったです。以下は覚え書き(抜けている人がいたら申し訳ないです

yasulab さん

来月の RubyKaigi の部屋の話やここ最近取り組んでいたプロジェクトの話を聞いてました。 Airbnb の宿自体はかなり前から予約していたらしく、かなり費用が安いとのこと。(住宅宿泊事業法が施行された後ではかなり料金が上がったらしいです

kyuden さん

今回実装していた llrbtree の実装にあたって参考にしたものを聞いてみたらスライドの中で紹介されてた この論文 だけとのこと。スゴイ。Ruby にも優先度付きキュー欲しいですねーという話をした。あと、自分も試しに赤黒木実装してみますと宣言してしまったので来月の RubyKaigi までには実装してみます。(一応前にやろうと思ったことがあったので)

yono さん

「お久しぶりですー」みたいな感じで話してた。Redmine 開発辛いトークを hanachin さんと楽しそうにやってました。

秒速さん

去年の RubyKaigi 以来で「お久しぶりですー」みたいな感じで話してました。「Okinawa.rb やばい」という話をしてましたが多分サンプリングが悪いと思っています。

koic さん

発表資料の中にあった LT の概要が気になったので聞きに行きました。 TracePoint の利用事例として面白かったです。自分の場合すぐ良くない方向で活用することを考えてしまうので、もっと役立つ方向で広めていきたいというお気持ち。

joker1007 さん

TracePoint トークをしてました。

このツイートの内容の詳細についてや、あと「AbstractSyntaxTree にパターンマッチほしいよねー」とか「TracePoint の b_call イベントで引数の値を取りたい」的な話など。

knu さん

SortedSet の話を聞きに行きました。実験的に実装したつもりがいつのまにか本体に取り込まれてしまったとのこと、自分は競技プログラミングをやっているので Ruby 本体で優先度付きキューが入ってくれると助かるのですが、厳しそうとのことでした(競技プログラミングでは 外部ライブラリを使うことが出来ないので本体に無いと使えない)

ujihisa さん

来月の RubyKaigi でローカル変数だけの話をする( Play with local vars )という話や今回発表していた内容について少し話しました。「Rubyフリップフロップを実装出来るか否か」みたいな話になって、その場では答えられなかったのですが、後々考えてみると rubinius の実装を見ればなんとかなるのではと思いました。(自分はまだ見てないです)フリップフロップ構文はもう deprecated な機能になってしまったのでそれがつらいみたいなことも話しました。

yui-knk さん

今回 AbstractSyntaxTree を触ってて色々気になったところを伺いに行きました。一通り疑問が解決出来たので良かったです。 Ruby の実行オプションである yydebug オプションをオススメされましたが、自分がこのオプションを有効活用出来るようになるのはまだ先な気がします。あと ドラゴン本 を紹介されました。