
# Testy wydajnościowe

Repozytorium zawiera zestaw testów wydajnościowych w lokalizacjach `bin/` i `benchmarks/`. Mierzy on każdy tryb wyszukiwania na rzeczywistych korpusach (WordPress, Laravel) oraz wygenerowanych syntetycznych zbiorach danych, zapisuje ustrukturyzowane raporty i umożliwia porównanie dwóch serii raportów.

Zestaw testów jest częścią repozytorium, a nie pakietu Composer: ponieważ 0.2.3, `benchmarks/` i skrypty `bin/bench*` są pomijane w pakiecie, uruchamiaj je ze sklonowanego repozytorium (`git clone https://github.com/inline0/greph && cd greph && composer install`).

Opublikowane wyniki w [README](https://github.com/inline0/greph#performance) pochodzą z uruchomień GitHub Actions, nigdy z komputerów lokalnych. Uruchomienia lokalne są przydatne podczas iteracji; źródłem prawdy są uruchomienia CI.

## Korpusy danych

Syntetyczne korpusy danych (`synthetic-1k`, `synthetic-10k`, `synthetic-100k-single`) są generowane w `benchmarks/corpora/synthetic/` przy pierwszym uruchomieniu. Rzeczywiste korpusy nie są dołączone: umieść kopię repozytorium w `benchmarks/corpora/wordpress` lub `benchmarks/corpora/laravel` (workflow CI klonuje `WordPress/WordPress` za pomocą `--depth=1`). Korpus z brakującym katalogiem jest pomijany.

## Uruchamianie testów wydajnościowych

```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` porównuje dwa pliki z seriami wyników (wyjście polecenia `bench-series` lub `bench-aggregate`) i wyświetla podsumowanie Markdown przydatne podczas optymalizacji krytycznej ścieżki. `bin/bench-ci` uruchamia workflow Benchmark w GitHub Actions za pośrednictwem `gh` CLI.

## Kategorie

README publikuje osiem grup wyników, z których każda mierzy konkretną warstwę silnika. Każda grupa obejmuje jedną lub więcej kategorii zestawu testów zdefiniowanych w `benchmarks/suites/`.

### Tryb skanowania: tekst

Natywne wyszukiwanie tekstu z użyciem wzorców dosłownych, wyrażeń regularnych i ich połączeń. Opublikowany wynik bazowy pochodzi z korpusu WordPress i obejmuje:

- Dosłowny `function`
- Dosłowny bez uwzględniania wielkości liter
- Dosłowny z dopasowaniem całych słów
- Nowa instancja wyrażenia regularnego
- Wywołanie tablicy wyrażeń regularnych
- Dosłowny prefiks wyrażenia regularnego
- Dosłowny sufiks wyrażenia regularnego
- Dosłowny pełny wiersz wyrażenia regularnego
- Upraszczanie dosłownych wyrażeń regularnych

### Tryb skanowania: przechodzenie po plikach

Samo przechodzenie po plikach, bez wyszukiwania. Mierzy koszt działania mechanizmu uwzględniającego gitignore.

### Tryb skanowania: tekst równoległy

Wyszukiwanie dokładnego ciągu `function` z użyciem `1`, `2` i `4` zadań. Dla tego wzorca pula procesów roboczych uruchamia się dopiero powyżej `jobs * 4_000` plików (zob. [Równoległe procesy robocze](https://greph.inline0.dev/pl/docs/advanced/parallel)), czyli liczby większej niż zawartość korpusu WordPress. Dlatego wszystkie trzy opublikowane wiersze działają w jednym procesie i nie pokazują skalowania puli ([#8](https://github.com/inline0/greph/issues/8)).

### Tryb skanowania: AST

Natywne wyszukiwanie AST z użyciem reprezentatywnych wzorców:

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

### Indeksowany tryb tekstowy

Rozgrzane indeksowane wyszukiwanie tekstu z użyciem tych samych wzorców co w trybie skanowania. Obejmuje zapytania dotyczące dopasowań dosłownych, bez uwzględniania wielkości liter, całych słów, krótkich tokenów i wyrażeń regularnych.

### Indeksowane zapytania podsumowujące

Rozgrzane indeksowane wyszukiwanie tekstu zwracające liczbę wyników, pliki z dopasowaniami i pliki bez dopasowań. Te zapytania najbardziej korzystają z magazynu wystąpień, ponieważ operacje na poszczególnych plikach są najtańsze.

### Indeksowane / buforowane AST

Rozgrzane wyszukiwanie faktów AST i wyszukiwanie AST z pamięci podręcznej przy użyciu tych samych wzorców co w trybie skanowania AST.

### Koszty kompilacji

Koszty zimnej kompilacji indeksu trigramowego, indeksu faktów AST i pamięci podręcznej AST. Przydatne przy wyborze trybu, który warto utrzymywać dla danego obciążenia.

## Jak odczytywać opublikowane wyniki

README publikuje migawkę najnowszego uruchomienia CI dla każdej wartości bazowej. Każda sekcja pochodzi z konkretnego uruchomienia GitHub Actions i zawiera oznaczenia korpusu, maszyny wykonawczej, wersji PHP oraz liczby mierzonych uruchomień i rozgrzewek. Aby odtworzyć wynik, użyj lokalnie tej samej konfiguracji.

Kolumny porównania (`rg`, `grep`, `sg`) są zbierane w ramach tego samego zadania, na tej samej maszynie wykonawczej i dla tego samego korpusu. Nie są ekstrapolowane z zewnętrznych testów wydajnościowych.

## Jak dodać test wydajnościowy

1. Dodaj definicję testu wydajnościowego w `benchmarks/`.
2. Dodaj odpowiedni scenariusz do zestawu regresji, jeśli jeszcze go tam nie ma, aby zweryfikować również mierzone zachowanie.
3. Uruchom `./bin/bench --category <yours>`, aby sprawdzić nowy test wydajnościowy.
4. Porównaj wyniki z `main` za pomocą workflow Benchmark, które uruchamia się dla żądań pull request dotyczących `src/`, `benchmarks/` lub `bin/` i publikuje porównanie bieżącej wersji z bazową w podsumowaniu uruchomienia.
5. Zaktualizuj tabelę README, gdy uruchomienie CI obejmujące nowy test zostanie scalone z `main`.

## Założenia dotyczące wydajności

Greph nie próbuje wyprzedzić ripgrep ani grep podczas zimnych skanów. Ripgrep jest zaimplementowany w Rust z ręcznie dostrojonym skanowaniem dosłownych ciągów za pomocą SIMD; w opublikowanych wynikach zarówno `rg`, jak i GNU `grep` są szybsze niż Greph podczas każdego zimnego skanowania tekstu. Cele są inne:

- Działać na tyle szybko, aby interakcja z narzędziem i praca agentów przebiegały naturalnie.
- Obsługiwać powtarzane zapytania za pomocą rozgrzanych indeksów: indeksowane zapytania dotyczące wyrażeń regularnych, liczby wyników i list plików są szybsze niż skanowanie tego samego drzewa przez `rg` i `grep`.
- Wyprzedzać `ast-grep` w indeksowanych i buforowanych obciążeniach AST, w których rozgrzane pamięci podręczne Greph pozwalają uniknąć ponownej analizy drzewa. Wyniki zimnego wyszukiwania AST są mieszane: `new $CLASS()` jest szybsze niż `sg`, a `array($$$ITEMS)` jest wolniejsze.
- Sprawiać, by każdy wzrost wydajności dało się zmierzyć i odtworzyć.

Twierdzenia dotyczące wydajności, które nie są poparte raportem z testów, nie są wdrażane.
