- Ubuntuで提供される
jqのソースコードパッケージを自分でビルドすると、性能が最大90%向上する可能性がある
- コンパイラ、最適化フラグ、メモリアロケータを改善することで性能を最大化する
設定
jqはJSON形式のGeoJSONファイル処理に使われる
- 500MBのAlameda County Assessor's parcel mapで、特定の値以上のすべてのparcelの都市名を出力するクエリを実行
- Ryzen 9 9950Xシステムで、キャッシュ済みファイル基準で約5秒かかるため、これを改善してみることにした
1段階: パッケージの再ビルド
- Launchpadから
jqのソースコードをダウンロードし、フラグなしで再ビルド
- 結果: 2〜4%性能向上
- ベンチマーク結果
- ビルドしたjq: 平均4.517秒
- Ubuntu標準パッケージ: 平均4.641秒
- 性能改善: 1.03倍高速化
2段階: Clangと高度な最適化フラグの使用
- Clang-18でコンパイルし、最適化レベルとLTOを使用
- 使用した主なフラグ:
-O3 → 最適化レベルを向上
-flto → Link-Time Optimizationを適用
-DNDEBUG → デバッグコードを除外
- ベンチマーク結果
- ビルドしたjq: 平均3.853秒
- Ubuntu標準パッケージ: 平均4.631秒
- 性能改善: 1.20倍高速化
3段階: TCMallocを追加
- GNU libcのデフォルトmallocの代わりにTCMallocを使用
-L/usr/lib/x86_64-linux-gnu -ltcmalloc_minimalを追加してビルド
- ベンチマーク結果
- ビルドしたjq: 平均3.253秒
- Ubuntu標準パッケージ: 平均4.611秒
- 性能改善: 1.42倍高速化
4段階: TCMallocの動的プリロードを適用
- Ubuntu標準パッケージで動的プリロードによりTCMallocを使用
- ベンチマーク結果
- 標準jq: 平均4.601秒
- TCMalloc適用jq: 平均4.082秒
- 性能改善: 1.13倍高速化
5段階: 別のアロケータの動的プリロードをテスト
- Ubuntuで提供される別のメモリアロケータであるjemallocとmimallocをテスト
- mimallocが最も優れた性能を提供
- ベンチマーク結果
- 標準jq: 平均4.123秒
- TCMalloc適用jq: 平均4.130秒
- jemalloc適用jq: 平均3.510秒
- mimalloc適用jq: 平均3.154秒 → 性能1.31倍向上
6段階: mimallocで直接ビルド
- mimallocを動的プリロードではなく静的リンク
- 性能を最大化
- ベンチマーク結果
- ビルドしたjq: 平均2.428秒
- Ubuntu標準パッケージ: 平均4.606秒
- 性能改善: 1.90倍高速化
🚀 最終結果
- Ubuntuパッケージより、自分でビルドしたjqのほうが90%高速
- 2.2GBのJSONファイル13,000件の処理性能:
- ビルドしたjq: 0.755秒
- 標準jq: 1.424秒
- 性能改善: 約2倍
1件のコメント
Hacker Newsのコメント
「Ubuntuパッケージを再構築し、メモリアロケータを変更して90%高速化する」というタイトルはクリックベイトっぽい
jemallocをプリロードしてmalloc実装を置き換えた経験があり、メモリ使用量の安定化に良い結果が得られたエンジニアリングは妥協の芸術である
Gentoo Linuxは、ユーザーの特定の用途に合わせて最適化できるよう設計されたオペレーティングシステムである
jqのようなパッケージを手動でインストールすると、セキュリティアップデートの対象外になる可能性があるoniguramaのセキュリティアップデートがあり、このような状況が再び起これば脆弱になる可能性がある非公式な
mallocを使うと奇妙なバグが発生することがある単純な変更で大きな高速化が得られると読んで、
jqの開発者に知らせたいと思ったパッケージをソースからコンパイルしたり、公式バイナリをダウンロードしたりすることは有益な場合がある
Rustの
cargo install機能は、特定プラットフォーム向けの最適化を可能にするため有用であるjaqとyqは、jqを使う際に性能向上のためによく使う選択肢であるメモリアロケータを変更した後にUbuntuパッケージを再構築すると、90%高速化できる可能性がある