RubyKaigi 2022
Day 1 (2022/9/8)
Ruby meets WebAssembly
Ruby 3.2で入る予定
CRuby/Swift/LLVM
ブラウザでRubyを動かしたい
RubyプログラムをWASMにコンパイルする話なのか? Rubyの言語処理系をWASMにコンパイルする話なのか?
後者だった
それはそうか
<script type="text/ruby">
CoffeeScriptっぽく見える
JSなのでページを開きなおすたびに環境が作りなおされる?
WASMでできないことはJSにやってもらう
Time.now (CRuby)
clock_gettime (syscall)
Date.now (JS)
WASI
WebAssembly System Interface
シングルバイナリじゃないといけない
WASI + VFS
RUBY_DESCRIPTION
WASMでは制御フローの操作が限定的
goto/call/return
Fiber
保守的GC
Asyncify
もともと非同期処理のために作られたがコールスタックを操作するのにも使える
Ruby on WASMの制約
スレッドまわりのAPIが使えない
C拡張ライブラリを静的リンクしないといけない
動的リンクのABIが仕様にないので誰も実装していない
Ruby Archaeology: Forgotten web frameworks
2022/9/8 13:36 途中から聴きはじめた
JSP/ASP/PHP style
マイグレーションを手書きしている
2006年とかだとまだRackがない?
March 02, 2007
Types teaches success, what will we do?
gem_rbs_collection
gemの型定義が少ない
全てのAPIの型定義を書かなければいけないわけではない
manifest.yml
gemspecに現れない依存関係を表現する
とくにないなら消してよい
Tools for Providing rich user experience in debugger
debug.gem
Chrome DevToolsでRubyプログラムをデバッグできる
リッチなUIでデバッグしたいけどVSCodeユーザーではない
タイムリープ
配列をテーブルやグラフにする (可視化)
ここからここまでください、というリクエストをデバッガに送る
Day 2 (2022/9/9)
Matz Keynote
Contribute to Ruby
海外のキーノートは録画
つ
Ruby is too good to be a scripting language
スクリプト言語にはオブジェクト指向はいらない
(さまざま言われる)
Rubyは毎年死んでる
フェアな批判ではない
価値を表す多くの言葉は "y" で終わる
Ruby
Productivity
Rails
Hotwire
少数のバックエンドチームだけでリッチなSPAを作れるように
Community
RubyGems.org
Joy
Money
2001年に初のRubyカンファレンス
来てくれた人は30人ぐらい
Top Ruby Companies
Top 50 Software Startups
Total Valuationの多くを占めている
コミュニティが鍵
名前の話
APL (A Programming Language)
トリアージが足りない
Ruby 3.2
パフォーマンス改善
WASM
Rubyがサポートするプラットフォームが1つ増えただけ、という印象だったが、思ったより反響が大きかった
YJIT
YJIT for ARM64
メモリアロケーション改善
MaNy (N:M threading)
Data objects
Data クラスはあったけど使われてなかった
3.2で再利用
Structクラスのimmutable版みたいな
syntax_suggest
ネストや括弧の対応を提案してくれる
error_highlight
ほかにもたくさん
ツールの充実によってRubyの生産性を上げたい
コアじゃない部分はC言語を強要しないほうがトータルで開発のベロシティが上がる
RuboCopのルールを選ぶのがだるい
Do Pure Ruby Dream of Encrypted Binary Protocol?
QUIC
再送要求をUDPの上に実装
Ruby, Ractor, QUIC (2021)
今回はRactorの話は出てこない
あきらめた
通信プロトコルの実装が難しい
まずは素朴に実装する
依存ライブラリを少なく
pure Rubyで
bit単位で意味を回復していく
unpack
変換を複数回行ってしまうミスが頻発
MessagePack
unpack部分はC言語
バイト列をIntegerの列として取り回したほうがよいのでは?
伏線
先頭に0があるとき、変換して戻ってきたときにおかしくなる
複数回unpackする問題への対策
再度unpackを呼べないようにする
BinData gem
Ractor内で使えない
文字列のまま扱いたい
XOR between byte
Pythonでもできない
Rust
bundle gem --rust
Rubyにバイト列クラスが入ったら嬉しいことはあるが、coreに入るとよいというと必ずしもそうではない
なぜ困難な道を選ぶのか
Ractorやmultithreadingにまつわる問題を回避するため
Make RuboCop super fast
RuboCop 10周年
RuboCop 2.0
パフォーマンスチューニング
解析結果のキャッシュ
マルチコア
使ってないrequireを削減する
内部に大きく手を入れないといけない
daemonize (server mode)
850倍高速化!!
rubocop CLIの中身
rubocop-daemon gem
TCPソケットを使って通信
rubocop-daemon-wrapper
1コマンドでサーバーの起動と解析ができる
rubocop-daemonを本体に統合するとよいのでは?
rubocop --server
server mode
exe/rubocop
なるべく必要なモジュールをメモリに乗せておく
Command line API design
rubocop-server という別コマンドにする?
emacsclient みたいなイメージ
rubocopのまま速くしたいはず
別コマンドよりは別オプションのほうがいいのでは
alias emacs='emacsclient -nw -a ""
--no-server
デフォルトで互換性がある
遅い
プロジェクトごとに使いたいルールが変わってくる
Dockerでラップしたい
serverオプションを渡さなかったときの挙動
安定しなかったらとりあえず再起動
サーバープロセスとキャッシュ
キャッシュのディレクトリにPIDやポート番号などを保存
バージョンが変わったらサーバーを再起動できるように
サーバーモードはまだデフォルトにはしない
third partyのgemをアップデートしてもauto-reloadしたい
UNIX domain socketを使ったら速くなりそうだけどまだ速くなっていない
測定から
オプションのalias
JRubyでも動くように
.rubocop ファイルでデフォルトのコマンドライン引数を指定できるように
Method-based JIT compilation by transpiling to Julia
Numo::NArrayやRed Arrow librariesを使うと大きなデータを効率的に扱えるが、MJITやYJITを使ってもあまり速くならない
MJITやYJITはRubyのセマンティクスを維持したネイティブコードを生成する
いつでもメソッドを再定義できる
動的メソッドディスパッチ
数値計算のようなアルゴリズムとは相性がよくない
無視してよいならドラスティックな最適化ができるはず
:soon: C拡張を書く!!
Rubyで書けないか?
Pythonの例
Numba (CPythonのJITコンパイラ)
Python + NumPyのサブセットを機械語に変換
CPythonのバイトコードを最適化する
nopython mode
nopython modeに近いJITコンパイラをRuby向けに作りたい
JuliaのJITコンパイル
RubyのメソッドをJuliaに変換したら後の変換はJuliaがやってくれる
「難しそうなことはJuliaにやらせよう」
変換の例
a...b → a:b
整数の範囲ならこれでもよいけど浮動小数点数の範囲ではダメ
ヘルパ関数を噛ませて変換
Juliaが得意な最適化をかけられるようにする
時間計算量が大きいアルゴリズムが高速化されやすい
配列の変換のオーバーヘッドが大きい
Heaping on the complexity! An adventure in GC Compaction
Rubyのヒープ
program heap
ruby heap
Embedded Allocation
metadata + data
dataが大きい場合は別の箇所に格納してポインタを保持する
cache lineに収まるならCPUキャッシュに入れる
ヒープに格納されたオブジェクトは参照局所性が低い
Variable Width Allocationによって解決しようとしている
RubyのGC
Stop the World
Mark-Sweep
世代GC
インクリメンタルGC
コンパクション
Two finger algorithm
はさみうちっぽい
Ruby 2.7から GC.compact が入った
それぞれのヒープを独立にコンパクションする
シンプル
ヒープのスキャン回数が多くて遅い
あとから書き換えたオブジェクトはリサイズできない
メモリの無駄が多い
オブジェクトの移動と参照の更新を独立にする
ヒープのスキャン回数が減って速い
プール間のオブジェクトの移動の制約がちょっと緩い
アルゴリズムが複雑
一方向にしかオブジェクトを移動できない
size pool inboxes
管理用のデータ領域が必要
GCの抽象化を外に持ち出している
Heapviz
Packet analysis with mruby on Wireshark - dRuby as example
Wireshark
protocol dissector
Wiresharkがプロトコルを解析するモジュール
自作してWiresharkに組み込む
LuaとC向けのAPIしかない
wireshark_with_mruby
Wiresharkにmrubyを組み込む
configファイル風のDSLでdissectorを書ける
handoff関数を読み込んでいる
WSProtocolクラスのインスタンスを復活させる
dRuby = Distributed Ruby
URIを経由してRubyコードを実行
WiresharkにはすでにdRubyパケットを解釈するdissectorがある
Create my own search engine.
自分のための手頃な問題を見つけて検索エンジンを作る
ポケカのデッキ検索ツール
2つのデッキの類似度を計算する
とくに探すものがなくても時間をつぶせる
Rubyとポケカは同じくらいの歴史がある
ポケカのカード検索サービス
カードに一意なIDを割り当てている
デッキ構築サービス
デッキコード
デッキがどのように登録されているのか外部から確認できない
デッキの表現
ベクトル化された文章に似ている
Bag of Cards
デッキの類似度
デッキは自然言語文章のサブセットとみなせる
ベクトル化は簡単
TF (あるカードが何枚採用されているのか)
IDF (全てのデッキで、あるカードがどれくらい採用されているのか、の逆数)
そのデッキの特徴となる (デッキ特有の) カードを出せる
sort_by -IDF
正規化
同じ効果・同じ意味のカードが複数枚ある
イラストがある
ミラー加工がある
card IDが異なる
カードが「同じ意味である」とは?
カードの種類によって判別方法が異なる
ポケモンのカードだけ面倒
card IDを正規化するための辞書
辞書は実行中に変わらない
diffを読みやすくするための工夫
たまに公式サイトが間違ってる
ほとんどの成分が0・内積計算しかしないことに特化したデータ構造にする
内積
マージソートっぽい
The dRuby Bookで説明していた
コサイン類似度
基本エネルギーカード問題
デッキには同じ名前のカードを4枚まで入れられる
基本エネルギーカードは何枚も入れられる
類似度に強く影響してしまう
デッキ類似度が最大のものを5件
いろんな検索ができる
Heroku
RIP Free Dyno
Dynoの性能がよくわからない
24時間に1度はDynoが再起動する
逆に再利用する
Heroku Postgres
Heroku Scheduler
クローラーの寿命とサービスの寿命は無関係
もしHerokuを使わなかったら?
中間データベース不要
d
Ruby Committers vs The World
Ruby 2.xはもうすぐ死ぬ
最新Unicode
Portable Ruby
RubyGems/Bundlerをもうちょっと使いやすくしたい
インストールバトルしなくてよいように
パーサーよくする
「悪魔城」
gem_rbs_collection
TypeProfを高速かつ便利にする
Rubyを高速にする
Rubyで並行・並列プログラムを気軽に書けるように
実世界のアプリケーションのスケーラビリティの問題を解決する
Rubyでデータ処理できるような環境を用意したい
配列の高速処理
パターンマッチング
Bug-Free Ruby
より自然なRuby
_1 vs it
@ はナシ
2個以上あるなら名前を付けてほしい
it は衝突が気になる
Data.def vs Data.define
Struct.new でクラスを作るのはおかしなデザインだったのではないか
Struct.define
2022/9/10
Why is building the Ruby environment hard?
2022/9/10 11:36 途中から聴きはじめた
Ubuntu 22.04でRubyを (簡単には) ビルドできない
OpenSSL 3.0だけが提供されるようになったので
OpenSSL 3.0はRuby 3.1しか対応していない
古いcompatible OpenSSLパッケージがない!!
ruby-buildでは適当なOpenSSLをビルドして使う
もともとはmacOSのLibreSSL向けの機能
バックポートできるか?
HerokuのRubyスタックは3.1しかない
macOSでRuby 2.6がビルドできない
fiddleでエラー
implicit declaration of function
Xcodeのツールチェーンがある時期から明確にエラーとして落とすようになった
Ruby 2.6はメンテナンス終了している
とりあえずエラーを抑制する
-DUSE_FFI_CLOSURE_ALLOC
とりあえずエラーが出ない、ぐらいの感じなので注意
macOS 13.0 (Ventura) でビルドできない
llvmの機能変更に追従するパッチがあてられた
forkのテストが動かない (固まる)
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
なぜか動く……
Venturaにアップデートするのは待ったほうがいい
人柱歓迎
mysql2がビルドできない
mysql_configが見つからない
libssl, libzstd
homebrewのOpenSSLを使っているとは限らない
mysql2-0.5.4で修正済み
bundled gemsがビルドできない
RubyGemsはインストール済みのRubyを想定してC拡張をビルドする
bundled gemsをスキップしてあとで入れる
Ruby 3.2で起こりそうなビルドエラー
YJITがRustになった
rustcが必要
ruby-buildでは自動判定している
3rd partyコードのバンドル
libyamlがないとエラーになる
コピーしたコードのメンテが大変なので消した
「何もしていないと壊れる」
Rubyはサメのように泳ぎ続けて変化し続ける言語
The Better RuboCop World to enjoy Ruby
株式会社万葉の英語表記はEveryleaf Corporationなのか
よりよくRuboCopを使っていくために何かできることはないか?
潜在的に大きなリスクがある
ルールは状況に合わないことがある
大多数のジュニアエンジニアはルールに従おうとする
RuboCopに通るようにコードを調整する……
RuboCop == 正しいRuby
状況に合わないルールに頻繁に引っかかる
開発速度が下がる
なにかの対処が必要になる
RuboCopの哲学
Rubyっぽいスタイルガイドは動的なのでは?
ルールの設定たいへんすぎる!!
コードのスタイルは静的に決まるかどうか
DSL
コード上の表現はスタイルではなく心である
「固さ」の度合いはルールごとに異なる
固ければ固いほど (ほとんどの状況で) 正しい
RuboCopの使い方を2つの系統に分けたらよさそう?
強制レベル
CIでガード
参考レベル
理想的なルールにする
違反ではなく参考情報として表示する
ただ1つの基準で分けられないものを分けようとするのをやめる!!
Fast data processing with Ruby and Apache Arrow
Rubyをデータ処理に使える言語にしたい
Apache Arrow
とくにBIツールにRubyを使いたい
たくさんのデータを高速に処理する用途だとまだ遅い
別プロセス
レスポンスが大きいと送受信のオーバーヘッドが大きい
Apache Arrowは速い
Flight SQL
gRPCベース
Dremioしか対応していない
Flight SQLは新しいプロトコルだから
互換性が重要
既存のプロトコルを喋れるとクライアントを使い回せる
ActiveRecordのアダプタを作ればよいはず
ADBC
Rubyバインディングを作っている
同一プロセス
もっと速い言語のライブラリが必要
Apache Arrowは計算モジュールも提供している
red_amber
DuckDB
Arrow DataFusion
C API経由のRubyバインディング
リモートデータ
低レベルAPIは実装できた
String Meets Encoding
String#split について
前回
Dive into Encoding
自作文字コードをCRubyに組み込む話
String#encode の高速化をしてほしい、というツイート
KEN_ALL.CSV
間違えて CSV.read の高速化をしてしまった
KEN_ALL.CSV
日本の郵便番号データ
CP932
ベンチマーク
CP932版とUTF8版
String#encode にはいくつか最適化が入っている
16MBのデータにしては遅い
stackprofで調査
メソッドの実行時間は調べられないので注意
String#splitが29.6%
CSVの各行でsplitが呼ばれる
perfでString#splitを観察する
速すぎると分からないのでデータや回数を増やす
rb_str_split_mが87.71%
ふたたびframegraph
CRubyでのString#splitの実装の流れ
rb_enc_cr_... が13%もかかっている
エンコーディングとcode rangeを部分文字列にコピーする
String#splitの性質
元の文字列のencodingを動的に計算せずにそのまま渡せばよいのでは?
そのように書き換えて実験
最大1.43倍速い
History of Japanese Ruby reference manual, and future
るりま
Rubyリファレンスマニュアル刷新計画
るびま
Rubyist Magazine
ネギま! に似ているけど関係はない
るりま以前の歴史
RD
iso-2022-jp
RWiki
RDの拡張
bitclustがRDベースの記法をサポート
ドキュメントのライセンス
bitclust時代の改善
EUC-JP → UTF-8
コード色付け
chmやePubへの出力
いまも使えるのかどうかは不明
現状
コピペ可能なサンプルコード
ドキュメントの内容更新
新しい構文にそこまで追従できていなさそう
どこに書けばよいかが明らかでない
rurema-review
活動できていない
RDベースの記法のドキュメントをMarkdownベースに変更したい
プリプロセッサの変換も含めた調査をしているところ
現行の文法
バージョン分岐
気にしていること
エディタ拡張機能のサポートを得られるか
既存のMarkdownプロセッサで変なことが起きないか
MethodList
f(args)
ブロックを受け取るメソッドの書き方が決まっていない
返り値の型があるけど活用されていない
リンク・リファレンス
ファイル内とファイル外で書き方が変わる
るりま関連のツールの使い方のドキュメント・ドキュメントの書き方のドキュメントが不足している
再現可能なビルド
サンプルコードの色付けがRubyのバージョンによって変わる
中期プランとしては、他のソフトウェアとの協調を進めたい
RBSとの連携
IRBとの連携
rdocの代わりに
実行可能なサンプルコードをWASMでブラウザ上で実行できるようにしたい
長期プラン
国際化したい
rdocとマージするのはかなり難しい
Stories from developing YJIT
no Rust related content
Rubyプログラムの実行の流れ
順に実行する
Railsだと遅い
frontend bound
frontendとbackendは何?
生成されたコードはエントリーポイントが多く分岐予測が効きづらい
Lazy Basic Block Versioning
stubを作る
実行時のデータに応じてstubを上書きしていく??
itselfメソッドを上書きする例
分岐は偏りがち
こうしてrailsbenchの高速化に成功
deoptimization
インタプリタの状態を再構築する
YJITでは必要なときだけプログラムカウンタを更新する
deoptimizationを回避する努力