Slide 1

Slide 1 text

RubyでRuby拡張を 書いたらRubyより 35倍速になったって どういうこと?? Kazuho Oku

Slide 2

Slide 2 text

● インターネットを、より速く・より安全・より効率化する仕事 をしています 普段のお仕事 2

Slide 3

Slide 3 text

● インターネットを、より速く・より安全・より効率化する仕事 をしています ○ Fastlyが使うHTTPサーバ「H2O」の設計実装 ■ HTTP/1.1, 2, 3, TLS, QUIC 普段のお仕事 3

Slide 4

Slide 4 text

● インターネットを、より速く・より安全・より効率化する仕事 をしています ○ Fastlyが使うHTTPサーバ「H2O」の設計実装 ■ HTTP/1.1, 2, 3, TLS, QUIC ○ 通信プロトコルの標準化 ■ HTTPの優先度制御や Early Hints ■ TLSのハンドシェイク暗号化 (Encrypted Client Hello) ■ QUICのパケット番号暗号化 普段のお仕事 4

Slide 5

Slide 5 text

● Rapid Startという、従来の「スロースタート」より立ち上が りが速い輻輳制御を設計〜導入した Rubykaigiで発表したこと 5

Slide 6

Slide 6 text

● Rapid Startという、従来の「スロースタート」より立ち上が りが速い輻輳制御を設計〜導入した ● その過程で、 jrfというjq的なツールを作った ○ Cで書かれている jqに対し、jrfはRuby Rubykaigiで発表したこと 6

Slide 7

Slide 7 text

● Rapid Startという、従来の「スロースタート」より立ち上が りが速い輻輳制御を設計〜導入した ● その過程で、 jrfというjq的なツールを作った ○ Cで書かれている jqに対し、jrfはRuby ○ Rubyだから ■ 単一スレッドで 3倍以上高速 ■ 自動並列化で 20倍以上高速 Rubykaigiで発表したこと 7

Slide 8

Slide 8 text

● Rapid Startという、従来の「スロースタート」より立ち上が りが速い輻輳制御を設計〜導入した ● その過程で、 jrfというjq的なツールを作った ○ Cで書かれている jqに対し、jrfはRuby ○ Rubyだから ■ 単一スレッドで 3倍以上高速 ■ 自動並列化で 20倍以上高速 ● cf. Rapid Start: Faster Internet Connections, with Ruby’s Help Rubykaigiで発表したこと 8

Slide 9

Slide 9 text

● CRubyは着実に速くなってるが、速くしてくのは大変 ○ cf. The design and implementation of ZJIT & the next five years Rubykaigiで聞いたこと 9

Slide 10

Slide 10 text

● CRubyは着実に速くなってるが、速くしてくのは大変 ○ cf. The design and implementation of ZJIT & the next five years ● 正規表現エンジンの呼び出しが複雑なこと、かと言って pure-Rubyだと遅いこと ○ cf. (Re)make Regexp in Ruby: Democratizing internals for the JIT Rubykaigiで聞いたこと 10

Slide 11

Slide 11 text

● CRubyは着実に速くなってるが、速くしてくのは大変 ○ cf. The design and implementation of ZJIT & the next five years ● 正規表現エンジンの呼び出しが複雑なこと、かと言って pure-Rubyだと遅いこと ○ cf. (Re)make Regexp in Ruby: Democratizing internals for the JIT ● Spinelという静的型推論を使う AOT処理系ができたこと ○ cf. Matz Keynote Rubykaigiで聞いたこと 11

Slide 12

Slide 12 text

● 型推論ができる範囲のコードなら C並に速くなるのか Matz Keynoteを聴きながら ... 12

Slide 13

Slide 13 text

● 型推論ができる範囲のコードなら C並に速くなるのか ● プロトコル実装や正規表現の処理系は、ステートマシンだ し、うまくハマりそうだな ... Matz Keynoteを聴きながら ... 13

Slide 14

Slide 14 text

● 型推論ができる範囲のコードなら C並に速くなるのか ● プロトコル実装や正規表現の処理系は、ステートマシンだ し、うまくハマりそうだな ... ● そして、Rubyから呼ばれる部分は APIに絞られるんだか ら、そこだけつないでやれば、 SpinelでRuby拡張書ける のでは... Matz Keynoteを聴きながら ... 14

Slide 15

Slide 15 text

東京に帰るぞ! …自転車で 15

Slide 16

Slide 16 text

● よし正規表現エンジンを Spinelで作ってみるぞ! 八戸駅から新幹線に乗りました 16

Slide 17

Slide 17 text

● よし正規表現エンジンを Spinelで作ってみるぞ! ● 「「「「AIが」」」」 八戸駅から新幹線に乗りました 17

Slide 18

Slide 18 text

regexpinelの設計方針 18 NFA engine nr_core_match関数 (regexpinel/core.rb) regexp compiler (lib/compiler*.rb) 命令 列 文字列 マッチ

Slide 19

Slide 19 text

regexpinelの設計方針 19 NFA engine nr_core_match関数 (regexpinel/core.rb) regexp compiler (lib/compiler*.rb) 命令 列 文字列 マッチ こいつをspinelでコンパイルし たC関数に差し替えたい

Slide 20

Slide 20 text

● spinelの生成するコードは GCを使ってはダメ ○ CRubyの中で別の ruby処理系を動かしたいわけでは ない Spinelを使ったCRuby拡張の作り方 20

Slide 21

Slide 21 text

● spinelの生成するコードは GCを使ってはダメ ○ CRubyの中で別の ruby処理系を動かしたいわけでは ない ● proof_vm_argv.rb: ○ コマンドラインで VM命令列、文字列を受け取り ○ nr_core_matchを呼び出し ○ マッチがある度に標準出力に出力 Spinelを使ったCRuby拡張の作り方 21

Slide 22

Slide 22 text

● spinelの生成するコードは GCを使ってはダメ ○ CRubyの中で別の ruby処理系を動かしたいわけでは ない ● proof_vm_argv.rb: ○ コマンドラインで VM命令列、文字列を受け取り ○ nr_core_matchを呼び出し ○ マッチがある度に標準出力に出力 Spinelを使ったCRuby拡張の作り方 22 spinelがコンパイルする コードでArray#pushする とGCが呼び出される!

Slide 23

Slide 23 text

● spinelの生成するコードは GCを使ってはダメ ○ CRubyの中で別の ruby処理系を動かしたいわけでは ない ● proof_vm_argv.rb: ○ コマンドラインで VM命令列、文字列を受け取り ○ nr_core_matchを呼び出し ○ マッチがある度に標準出力に出力 ● ↑ これをspinelでコンパイル Spinelを使ったCRuby拡張の作り方 23 spinelがコンパイルする コードでArray#pushする とGCが呼び出される!

Slide 24

Slide 24 text

● spinelの生成するコードは GCを使ってはダメ ○ CRubyの中で別の ruby処理系を動かしたいわけでは ない ● proof_vm_argv.rb: ○ コマンドラインで VM命令列、文字列を受け取り ○ nr_core_matchを呼び出し ○ マッチがある度に標準出力に出力 ● ↑ これをspinelでコンパイル ○ main関数を消す ○ マッチ位置を出力してる部分を差し替え Spinelを使ったCRuby拡張の作り方 24 spinelがコンパイルする コードでArray#pushする とGCが呼び出される!

Slide 25

Slide 25 text

github.com/kazuho/regexpinel 成果物 25

Slide 26

Slide 26 text

ベンチマーク 26

Slide 27

Slide 27 text

短い文字列のマッチ 27 Ops/秒 vs. CRuby CRuby Regexp 19,037,261 1.00x Regexpinel (pure-Ruby) 902,166 0.05x Regexpinel (compiled) 31,925,547 1.68x

Slide 28

Slide 28 text

短い文字列のマッチ 28 Ops/秒 vs. CRuby CRuby Regexp 19,037,261 1.00x Regexpinel (pure-Ruby) 902,166 0.05x Regexpinel (compiled) 31,925,547 1.68x 35倍速!!!

Slide 29

Slide 29 text

短い文字列の sub 29 Ops/秒 vs. CRuby CRuby Regexp 5,180,703 1.00x Regexpinel (pure-Ruby) 389,489 0.08x Regexpinel (compiled) 12,814,179 2.47x

Slide 30

Slide 30 text

短い文字列の gsub 30 Ops/秒 vs. CRuby CRuby Regexp 3,168,890 1.00x Regexpinel (pure-Ruby) 295,045 0.09x Regexpinel (compiled) 10,993,974 3.47x

Slide 31

Slide 31 text

長い文字列のマッチ (MB/s) 31 CRuby Regexpinel (pure-Ruby) Regexpinel (compiled) z*ab (マッチ) 362.2 1.0 349.3 z*ab (ミス) 3,918.6 1.0 345.1 a+b (マッチ) 417.0 1.1 439.6 a+b (ミス) 413.7 1.1 415.3 é*x (マッチ) 387.8 2.1 668.6

Slide 32

Slide 32 text

まとめ 32

Slide 33

Slide 33 text

● CRubyが、もっと速くなるといいな ○ そしたらなんでも Rubyで書けるし ● 待てないなら Spinelで拡張を書くのも面白い! ○ 既存手法 (Cライブラリと組み合わせ ) より速くなったよ まとめ 33