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

`go get`したらELFが降ってきた件

Avatar for 鹿 鹿
October 31, 2026

`go get`したらELFが降ってきた件

github.com/velox-io/json の native acceleration の仕組みを調べてみました。
すごい黒魔術です。

Avatar for 鹿

鹿

October 31, 2026

More Decks by 鹿

Other Decks in Technology

Transcript

  1. github.com/velox-io/json • Podcast 『八百万のOSS』 #25 「go-jsonはなぜ速いのか」で紹介 • Go の高性能 JSON

    ライブラリ • encoding/json 風のAPI • amd64/arm64 ではネイティブで高速 • 作者のベンチマークでは、velox-ioはJSONv2の7%〜41%の処理時間 • さらに、go-jsonよりも速いそう
  2. It uses native acceleration on supported platforms and pure Go

    elsewhere • なるほど、cgo で書いてるのかな? • でもなんでプラットフォームが限定?アセンブラ利用? • cloneして中を見ると、ELFバイナリが置いてある % git clone https://github.com/velox-io/json % cd json % find native -name '*.elf' native/encvm/encvm_arm64.elf native/encvm/encvm_amd64.elf native/ndec/ndec_amd64.elf native/ndec/ndec_arm64.elf native/vlib/internal/nativeref/vlib_arm64.elf native/vlib/internal/nativeref/vlib_amd64.elf
  3. ELF (Executable and Linkable Format) • Linux, *BSD などの実行形式 •

    macOS (darwin) は Mach-O • じゃあ macOS では native acceleration は出来ない? • 出来ます! • 本当に?
  4. ベンチマーク • 35MBのJSONのUnmarshal を繰り返すbench • go 1.27.3 • github.com/goccy/go-json v0.11.2

    • github.com/velox-io/json v0.4.4 • ※入力バッファを流用しない版でそろえた • on Apple M1 MAX MacBook Pro BenchmarkUnmarshalStd-10 BenchmarkUnmarshalGoJSON-10 BenchmarkUnmarshalVeloxCopy-10 • Std -> go-json は x0.25 • Std -> velox-io は x0.15 • 確かに速い 5 220989567 ns/op 166.78 MB/s 168171168 B/op 1326991 allocs/op 21 54326377 ns/op 678.42 MB/s 51958075 B/op 232535 allocs/op 33 32098043 ns/op 1148.23 MB/s 50191388 B/op 9576 allocs/op
  5. 仕組み • ELFの実行形式バイナリをembed • cgoではない • 子プロセスではない • プロセスのメモリで直接実行する •

    起動時にELFを実行可能メモリへmapする • 利点:Cコンパイラ不要、1バイナリに、OSごとのビルド分け不要 • 疑問:本当に動くの?安全なの?
  6. Unmarshal時の動作イメージ • C製のVMがGoのオブジェク トを直接構築する • 状態はVM内に保存 • メモリ確保などGoにしかで きない処理はyieldしてGo に戻る(回数も最低限に)

    • JSONパース中はGo側で到 達可能に保ちGCも安全 • GoのmapのSwiss tableも 直接操作(メモリレイアウト を知ってる)
  7. 個人的な疑問 • なぜVMをCで? • フローの精密な制御 • コンパイラ最適化 • なぜ cgo

    ではないの? • 利用時にCコンパイラが不要、archが同じならOSやリンカに依存せず使える • (推測)ABI変換切り替えの負荷を避けた?Go側のスタックをC VMから使うため? • なぜ dlopen ではないの? • (推測)cgo前提になるし、OSの作法に縛られるから? • embedしたバイナリを実行できるの? • LinuxではRWでmmap→copy→mprotect(R|X) • darwinではMAP_JITで書き込み、JIT関連の機能を使う • その他、AIに聞いたら工夫が凄すぎた
  8. まとめ • velox-io/json は(作者のベンチマークによると)Go界最速 • ELFバイナリをembed→実行時にメモリにマップ→Goと協調して動作 • 利用者はコンパイルしなくてもネイティブ実行可能 • archごとに一つのELFバイナリで、複数のOSをサポート

    (linux/darwin/windows) • 環境依存と互換性リスクが高い • メモリへのマップの仕組みはOS固有 • 実行時のメモリ制約では動かないかも(推測) • Goランタイムの内部レイアウトに依存