Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

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

Avatar for kazuho

kazuho

May 25, 2026

More Decks by kazuho

Other Decks in Technology

Transcript

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

    QUIC ◦ 通信プロトコルの標準化 ▪ HTTPの優先度制御や Early Hints ▪ TLSのハンドシェイク暗号化 (Encrypted Client Hello) ▪ QUICのパケット番号暗号化 普段のお仕事 4
  2. • Rapid Startという、従来の「スロースタート」より立ち上が りが速い輻輳制御を設計〜導入した • その過程で、 jrfというjq的なツールを作った ◦ Cで書かれている jqに対し、jrfはRuby

    ◦ Rubyだから ▪ 単一スレッドで 3倍以上高速 ▪ 自動並列化で 20倍以上高速 • cf. Rapid Start: Faster Internet Connections, with Ruby’s Help Rubykaigiで発表したこと 8
  3. • 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
  4. • 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
  5. regexpinelの設計方針 19 NFA engine nr_core_match関数 (regexpinel/core.rb) regexp compiler (lib/compiler*.rb) 命令

    列 文字列 マッチ こいつをspinelでコンパイルし たC関数に差し替えたい
  6. • spinelの生成するコードは GCを使ってはダメ ◦ CRubyの中で別の ruby処理系を動かしたいわけでは ない • proof_vm_argv.rb: ◦

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

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

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

    コマンドラインで VM命令列、文字列を受け取り ◦ nr_core_matchを呼び出し ◦ マッチがある度に標準出力に出力 • ↑ これをspinelでコンパイル ◦ main関数を消す ◦ マッチ位置を出力してる部分を差し替え Spinelを使ったCRuby拡張の作り方 24 spinelがコンパイルする コードでArray#pushする とGCが呼び出される!
  10. 短い文字列のマッチ 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
  11. 短い文字列のマッチ 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倍速!!!
  12. 短い文字列の 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
  13. 短い文字列の 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
  14. 長い文字列のマッチ (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