
# ベンチマーク

リポジトリには`bin/`と`benchmarks/`の下にベンチマークハーネスがあります。実データのコーパス（WordPress、Laravel）と生成した合成データセットを使って各検索モードを測定し、構造化レポートを収集して、2つのレポート系列を比較できます。

ハーネスはリポジトリの一部であり、Composerパッケージには含まれません。0.2.3以降、`benchmarks/`と`bin/bench*`スクリプトはパッケージから除外されています。クローン（`git clone https://github.com/inline0/greph && cd greph && composer install`）から実行してください。

[README](https://github.com/inline0/greph#performance)に掲載されている測定値は、GitHub Actionsの実行結果に基づいており、ローカルマシンでの測定値は使っていません。ローカル実行は反復開発に役立ちますが、正式な基準となるのはCIの実行結果です。

## コーパス

合成コーパス（`synthetic-1k`、`synthetic-10k`、`synthetic-100k-single`）は、初回実行時に`benchmarks/corpora/synthetic/`の下に生成されます。実データのコーパスは含まれていません。`benchmarks/corpora/wordpress`または`benchmarks/corpora/laravel`にチェックアウトを配置してください（CIワークフローは`--depth=1`を使って`WordPress/WordPress`をクローンします）。ディレクトリが見つからないコーパスはスキップされます。

## ベンチマークの実行

```bash
# Full benchmark suite, every corpus that is present
./bin/bench

# Specific category (the category names used in benchmarks/suites/)
./bin/bench --category text
./bin/bench --category ast

# Compare against external tools when available
./bin/bench --compare rg,grep
./bin/bench --compare sg

# Choose a corpus
./bin/bench --corpus wordpress
./bin/bench --corpus laravel
./bin/bench --corpus synthetic-1k

# Write the run as JSON
./bin/bench --corpus wordpress --output build/run-1.json

# Measured series: 5 runs after 1 warmup run
./bin/bench-series --repeat 5 --warmup 1 --corpus wordpress --output build/head-series.json

# Aggregate separate runs into one series
./bin/bench-aggregate --output build/head-series.json build/run-*.json
```

`bin/bench-compare base-series.json head-series.json`は2つの系列ファイル（`bench-series`または`bench-aggregate`の出力）を比較し、Markdownの概要を表示します。処理が集中する箇所の改善を繰り返す際に便利です。`bin/bench-ci`は、`gh` CLIを通じてGitHub Actionsのベンチマークワークフローを起動します。

## カテゴリー

READMEでは、エンジンの特定の層を測定する8つの結果グループを公開しています。各グループには、`benchmarks/suites/`で定義された1つ以上のハーネスカテゴリーが含まれます。

### スキャンモード: テキスト

リテラル、正規表現、組み合わせパターンを使ったネイティブのテキスト検索です。公開されているベースラインはWordPressコーパスで実行され、以下を含みます:

- リテラル`function`
- 大文字小文字を区別しないリテラル
- 単語全体のリテラル
- 新しいインスタンスでの正規表現
- 配列呼び出しでの正規表現
- 接頭辞リテラルの正規表現
- 接尾辞リテラルの正規表現
- 行全体と一致するリテラルの正規表現
- リテラルをまとめた正規表現

### スキャンモード: トラバーサル

検索を行わず、ファイルの走査のみを実行します。gitignore対応のウォーカー単体のコストを測定します。

### スキャンモード: 並列テキスト

`function`を`1`、`2`、`4`ジョブで検索する固定文字列検索です。このパターンでは、ワーカープールが起動するのは`jobs * 4_000`ファイルを超える場合だけです（[並列ワーカー](https://greph.inline0.dev/ja/docs/advanced/parallel)を参照）。WordPressコーパスはその数に満たないため、公開されている3つの行はすべて単一プロセスで実行され、プールの拡張性を示していません（[#8](https://github.com/inline0/greph/issues/8)）。

### スキャンモード: AST

代表的なパターンを使ったネイティブAST検索:

- `new $CLASS()`
- `array($$$ITEMS)`

### インデックス付きテキストモード

スキャンモードと同じパターンを使った、ウォーム状態のインデックス付きテキスト検索です。リテラル、大文字小文字を区別しない検索、単語全体の検索、短いトークン、正規表現クエリを含みます。

### インデックス付き概要クエリ

件数、一致するファイル、一致しないファイルを出力する、ウォーム状態のインデックス付きテキスト検索です。ファイルごとの処理が最も少ないため、転置インデックスの恩恵を特に受けます。

### インデックス付き／キャッシュ済みAST

ASTスキャンモードと同じパターンを使った、ウォーム状態でのAST事実検索とキャッシュ済みAST検索です。

### ビルドコスト

トライグラムインデックス、AST事実インデックス、ASTキャッシュのコールドビルド時のコストです。ワークロードに応じて維持するモードを決める際に役立ちます。

## 公開されている測定値の読み方

READMEでは、各ベースラインについて最新のCI実行結果を掲載しています。各セクションには、測定元のGitHub Actionsの実行と、コーパス、ランナー、PHPのバージョン、測定回数、ウォームアップ回数が記載されています。数値を再現する場合は、ローカルで同じ組み合わせを使用してください。

比較列（`rg`、`grep`、`sg`）は、同じジョブ内で、同じランナーとコーパスを使って収集しています。外部のベンチマークから推定した値ではありません。

## ベンチマークの追加方法

1. `benchmarks/`の下にベンチマーク定義を追加します。
2. 同等のシナリオがまだない場合は、回帰テストスイートに対応するシナリオを追加します（測定対象の動作も検証できるようにします）。
3. `./bin/bench --category <yours>`を実行して、新しいベンチマークを検証します。
4. ベンチマークワークフローで`main`と比較します。このワークフローは、`src/`、`benchmarks/`、`bin/`に関係するプルリクエストで実行され、実行概要に変更前後の比較を投稿します。
5. 新しいベンチマークを含むCI実行が`main`に反映されたら、READMEの表を更新します。

## パフォーマンスに関する方針

Grephは、低温時のスキャンでripgrepやgrepを上回ることを目指していません。RipgrepはRustで実装され、手作業で調整したSIMDリテラルスキャンを使います。公開されている数値では、`rg`とGNU`grep`は、すべての低温テキストスキャンでGrephより高速です。目指すものはそれぞれ異なります。

- 対話的な利用やエージェントの処理ループで、ネイティブに感じられるほど高速にする。
- ウォーム状態のインデックスから繰り返しのクエリに応答する。インデックス付きの正規表現、件数、ファイル一覧のクエリは、同じツリーをスキャンする`rg`と`grep`の両方より高速です。
- インデックス付きおよびキャッシュ済みASTのワークロードで`ast-grep`を上回る。Grephはウォームキャッシュによりツリーの再解析を避けられます。コールドAST検索の結果は一様ではなく、`new $CLASS()`は`sg`より高速ですが、`array($$$ITEMS)`は低速です。
- パフォーマンス改善をすべて測定可能かつ再現可能にする。

ベンチマークレポートで裏付けられていないパフォーマンスの主張は採用されません。
