
# 基准测试

仓库在 `bin/` 和 `benchmarks/` 下提供基准测试工具。它会使用真实语料库（WordPress、Laravel）和生成的合成数据集测试每种搜索模式，捕获结构化报告，并支持比较两组报告序列。

该工具属于仓库，而非 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 运行结果才是权威依据。

## 语料库

首次运行时，会在 `benchmarks/corpora/synthetic/` 下生成合成语料库（`synthetic-1k`、`synthetic-10k`、`synthetic-100k-single`）。真实语料库不包含在内：请在 `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` 可比较两个序列文件（`bench-series` 或 `bench-aggregate` 的输出）并打印 Markdown摘要，便于针对热点路径进行迭代。`bin/bench-ci` 会通过 `gh` CLI 在 GitHub Actions 上触发 Benchmark 工作流。

## 类别

README 会发布八组结果，每组衡量引擎的一个特定层级。每组汇集一个或多个在 `benchmarks/suites/` 中定义的工具类别。

### 扫描模式：文本

使用原生文本搜索匹配字面量、正则表达式及组合模式。发布的基线测试在 WordPress 语料库上运行，包含：

- 字面量 `function`
- 字面量，不区分大小写
- 字面量，全字匹配
- 新建实例的正则表达式
- 正则表达式数组调用
- 正则表达式前缀字面量
- 正则表达式后缀字面量
- 正则表达式精确行字面量
- 正则表达式字面量合并

### 扫描模式：遍历

仅遍历文件，不执行搜索。单独衡量支持 gitignore 的遍历器开销。

### 扫描模式：并行文本

使用 `1`、`2` 和 `4` 个任务，对 `function` 执行固定字符串搜索。对于该模式，只有文件数超过 `jobs * 4_000` 时工作线程池才会启动（参见 [并行工作线程](https://greph.inline0.dev/zh/docs/advanced/parallel)）；文件数高于 WordPress 语料库，因此发布的三行数据都在单个进程中运行，无法体现线程池扩展效果（[#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. 使用 Benchmark 工作流与 `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)` 更慢。
- 让每项性能提升都可测量、可复现。

没有基准测试报告支持的性能声明不会合入。
