
# Benchmarks

O repositório inclui uma ferramenta de benchmarks em `bin/` e `benchmarks/`. Ela mede cada modo de pesquisa com conjuntos de dados reais (WordPress, Laravel) e conjuntos sintéticos gerados, captura relatórios estruturados e permite comparar duas séries de relatórios.

A ferramenta faz parte do repositório, não do pacote Composer: como 0.2.3, `benchmarks/` e os scripts `bin/bench*` não são incluídos no pacote, execute-os a partir de um clone (`git clone https://github.com/inline0/greph && cd greph && composer install`).

Os números publicados em [README](https://github.com/inline0/greph#performance) vêm de execuções do GitHub Actions, nunca de máquinas locais. As execuções locais são úteis para iterar; as execuções do CI são a fonte confiável.

## Conjuntos de dados

Os conjuntos sintéticos (`synthetic-1k`, `synthetic-10k`, `synthetic-100k-single`) são gerados em `benchmarks/corpora/synthetic/` na primeira execução. Os conjuntos reais não estão incluídos: coloque um checkout em `benchmarks/corpora/wordpress` ou `benchmarks/corpora/laravel` (o fluxo de trabalho do CI clona `WordPress/WordPress` com `--depth=1`). Um conjunto cujo diretório não exista será ignorado.

## Executar benchmarks

```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` compara dois arquivos de séries (a saída de `bench-series` ou `bench-aggregate`) e exibe um resumo Markdown, útil ao iterar em um caminho crítico. `bin/bench-ci` aciona o fluxo de trabalho Benchmark em GitHub Actions pelo `gh` CLI.

## Categorias

README publica oito grupos de resultados, cada um medindo uma camada específica do mecanismo. Cada grupo reúne uma ou mais categorias da ferramenta definidas em `benchmarks/suites/`.

### Modo de varredura: texto

Pesquisa nativa de texto com padrões literais, regex e combinados. A linha de base publicada usa o conjunto WordPress e inclui:

- `function` literal
- Literal sem distinção entre maiúsculas e minúsculas
- Palavra inteira literal
- Nova instância de regex
- Chamada de matriz de regex
- Literal como prefixo de regex
- Literal como sufixo de regex
- Literal de linha exata de regex
- Colapso de literal de regex

### Modo de varredura: travessia

Percorrimento de arquivos sem pesquisa. Mede somente o custo do percorrimento que respeita gitignore.

### Modo de varredura: texto paralelo

Pesquisa de cadeia fixa por `function` com `1`, `2` e `4` tarefas. Para esse padrão, o conjunto de workers só é iniciado acima de `jobs * 4_000` arquivos (consulte [Workers paralelos](https://greph.inline0.dev/pt/docs/advanced/parallel)); o conjunto WordPress contém menos arquivos. Por isso, todas as três linhas publicadas são executadas em um único processo e não mostram o escalonamento do conjunto ([#8](https://github.com/inline0/greph/issues/8)).

### Modo de varredura: AST

Pesquisa nativa de AST com padrões representativos:

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

### Modo de texto indexado

Pesquisa de texto indexado aquecido com os mesmos padrões do modo de varredura. Inclui consultas literais, sem distinção entre maiúsculas e minúsculas, de palavra inteira, de tokens curtos e regex.

### Consultas de resumo indexadas

Pesquisa de texto indexado aquecido com saídas de contagem, arquivos com correspondências e arquivos sem correspondências. Essas consultas se beneficiam mais do armazenamento de ocorrências porque o trabalho por arquivo é o mais barato.

### AST indexada/em cache

Pesquisa aquecida de fatos de AST e pesquisa de AST em cache com os mesmos padrões do modo de varredura de AST.

### Custos de compilação

Custos de compilação a frio para o índice de trigramas, o índice de fatos de AST e o cache de AST. Útil para decidir qual modo manter para uma determinada carga de trabalho.

## Como interpretar os números publicados

README publica uma captura da execução mais recente do CI para cada linha de base. Cada seção vem de uma execução específica do GitHub Actions e está identificada com o conjunto de dados, o executor, a versão PHP e o número de execuções medidas e aquecimentos. Para reproduzir um número, use a mesma combinação localmente.

As colunas de comparação (`rg`, `grep`, `sg`) são coletadas na mesma tarefa, no mesmo executor e com o mesmo conjunto de dados. Elas não são extrapoladas de benchmarks externos.

## Como adicionar um benchmark

1. Adicione uma definição de benchmark em `benchmarks/`.
2. Adicione um cenário correspondente à suíte de regressão se ainda não houver um equivalente (assim, o comportamento medido também é verificado).
3. Execute `./bin/bench --category <yours>` para validar o novo benchmark.
4. Compare com `main` usando o fluxo de trabalho Benchmark, executado em solicitações de pull que alteram `src/`, `benchmarks/` ou `bin/` e publica uma comparação entre a revisão atual e a base no resumo da execução.
5. Atualize a tabela README quando a execução do CI que inclui o novo benchmark chegar a `main`.

## Filosofia de desempenho

Greph não tenta superar ripgrep ou grep em varreduras a frio. Ripgrep é implementado em Rust com varredura literal SIMD ajustada manualmente e, nos números publicados, tanto `rg` quanto GNU `grep` são mais rápidos que Greph em todas as varreduras de texto a frio. Os objetivos são diferentes:

- Ser rápido o bastante para que o uso interativo e os ciclos dos agentes pareçam nativos.
- Responder a consultas repetidas usando índices aquecidos: consultas de regex indexadas, de contagem indexadas e de lista de arquivos são mais rápidas do que a varredura de mesma árvore por `rg` e `grep`.
- Superar `ast-grep` em cargas de trabalho de AST indexada e em cache, nas quais os caches aquecidos de Greph evitam analisar novamente a árvore. A pesquisa de AST a frio tem resultados mistos: `new $CLASS()` é mais rápido que `sg`, `array($$$ITEMS)` é mais lento.
- Tornar cada melhoria de desempenho mensurável e reproduzível.

Alegações de desempenho sem respaldo em um relatório de benchmark não são aceitas.
