正確性、速度、そしてシンプルさに重点を置いた jq クローン、Jaq
(github.com/01mf02)jaq の紹介
- jaq は JSON データ処理ツール jq のクローンであり、jq の構文と演算の大部分をサポートすることを目指している。
- jaq の3つの主要な目標は 正確性、性能、そして シンプルさ である。
- jq との互換性を保ちながら、より正確で予測可能な実装を提供しようとしている。
- jq の予期しない挙動の例として、
nan > nanが偽でnan < nanが真になることや、jqで[[[]] | implodeを実行するとクラッシュが発生することなどがある。 - jq の長い起動時間への対策として開発されており、jq 1.6 と比べて約30倍速い起動時間を誇る。
- jaq はバグの可能性を減らし、コントリビュートを容易にするため、シンプルで小規模な実装を目指している。
インストール方法
ソースからインストール
- jaq をコンパイルするには Rust ツールチェーンが必要である。
- Linux ディストリビューションに含まれる Rust コンパイラは古く、jaq のコンパイルには適していない場合がある。
cargo install --locked jaqまたはcargo install --locked --git https://github.com/01mf02/jaqコマンドで jaq をインストールできる。- Rust がサポートするすべてのシステムで jaq は動作するはずであり、そうでない場合は issue を起票すべきである。
バイナリのインストール
- macOS または Linux では Homebrew を使って jaq をインストールできる。
例
- 以下の例は、jaq が現在できることを示している。
echo '{"a": 1, "b": 2}' | jaq '.a'を実行すると1が出力される。echo '{"a": 1, "b": 2}' | jaq 'add'を実行すると3が出力される。echo '[0, 1, 2, 3]' | jaq 'map(.*2) | [.[] | select(. < 5)]'を実行すると[0, 2, 4]が出力される。
パフォーマンス
- 複数のベンチマークを通じて jaq、jq、gojq の性能を比較している。
emptyベンチマークは起動時間を測定するために使われる。bf-fibベンチマークでは、jq で書かれた Brainfuck インタプリタが Fibonacci 数を生成する Brainfuck スクリプトを実行する。- 他のベンチマークでは、さまざまなフィルタを入力値
nとともに評価する。 - ベンチマーク結果は、jaq-1.2 が 16 個のベンチマークで最速、jq-1.7 は 2 個、gojq-0.12.13 は 1 個で最速だったことを示している。
機能
基本機能
- 基本データ型、条件分岐、アクセス、演算子、エラー処理、文字列補間、フォーマット文字列など、さまざまな基本機能をサポートしている。
パス
- 配列/オブジェクトのインデクシング、反復、オプションのインデクシング/反復、配列スライス、文字列スライスなどをサポートしている。
演算子
- 合成、束縛、連結、代入、更新代入、代替、論理、等価性と比較、算術、否定、エラー抑制などの演算子をサポートしている。
定義
- 基本定義と再帰定義をサポートしている。
コアフィルタ
- さまざまなコアフィルタをサポートしている。
標準フィルタ
- 標準フィルタは、より基本的なフィルタを通じて定義される。
数値フィルタ
- libm から取り込まれた多くのフィルタをサポートしている。
高度な機能
- モジュール、SQL スタイル演算子、ストリーミングなど、jq の一部機能はサポートしていない。
jq と jaq の違い
数値
- jq はすべての数値を 64 ビット浮動小数点として扱う一方、jaq は整数と浮動小数点を区別して扱う。
NaN と無限大
- jaq は IEEE 754 浮動小数点演算標準により近い挙動を提供する。
小数値の保持
- jaq は JSON データに由来する小数値を完全に保持する。
代入
- jaq は代入を jq とは異なる形で解釈する。
定義
- jaq はフィルタ定義を許可し、jq と同様に引数を値として渡せる。
引数
- jaq はコマンドラインを通じて引数を定義できる。
畳み込み
- jaq は
reduceとforeachフィルタを提供し、jq とは異なる解釈を行う。
エラー処理
- jaq は jq とは異なるエラー処理メカニズムを使う。
その他
- スラーピング、デカルト積、リスト更新、入力の読み取り、結合などで jq と jaq は異なる挙動を示す。
コントリビュート
- jaq へのコントリビュートを歓迎しており、変更後に
cargo testが正常に実行されることを確認する必要がある。
謝辞
- jaq は複数のライブラリと Rust 標準ライブラリのおかげで大きな恩恵を受けている。
GN⁺ の見解
この記事で最も重要なのは、jaq が jq の機能の大半をサポートしながら、性能と正確性の向上を目指している点である。特に、起動時間が jq と比べて大幅に速く、予期しない挙動を減らそうとしている点は、多くのユーザーにとって興味深いだろう。また、Rust ベースで開発されているため、メモリ安全性と性能の面でも利点がある。こうした改善は、JSON データ処理を必要とするソフトウェアエンジニアにとって有用なツールになると期待される。
1件のコメント
Hacker Newsのコメント
nan > nanが偽でnan < nanが真になるのは、浮動小数点標準である IEEE 754 に忠実に従ったものなのか、それともバグなのかという疑問が提起されている。