
# Тестування продуктивності

У репозиторії є набір інструментів для тестування продуктивності в `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.

## Корпуси даних

Синтетичні корпуси даних (`synthetic-1k`, `synthetic-10k`, `synthetic-100k-single`) генеруються в `benchmarks/corpora/synthetic/` під час першого запуску. Реальні корпуси не включено: розмістіть копію репозиторію в `benchmarks/corpora/wordpress` або `benchmarks/corpora/laravel` (процес CI клонує `WordPress/WordPress` за допомогою `--depth=1`). Корпус із відсутнім каталогом пропускається.

## Запуск тестування продуктивності

```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` запускає процес Benchmark на GitHub Actions через `gh` CLI.

## Категорії

README публікує вісім груп результатів, кожна з яких вимірює окремий рівень рушія. Кожна група охоплює одну або кілька категорій набору інструментів, визначених у `benchmarks/suites/`.

### Режим сканування: текст

Власний текстовий пошук за літеральними, регулярними та комбінованими шаблонами. Опублікований базовий результат отримано на корпусі WordPress; він охоплює:

- Літеральний `function`
- Літеральний без урахування регістру
- Літеральний пошук цілих слів
- Регулярний вираз, новий екземпляр
- Масивний виклик регулярного виразу
- Літеральний префікс у регулярному виразі
- Літеральний суфікс у регулярному виразі
- Літеральний пошук точного рядка в регулярному виразі
- Згортання літералів у регулярному виразі

### Режим сканування: обхід

Лише обхід файлів, без пошуку. Вимірює окремо витрати на обхід із підтримкою gitignore.

### Режим сканування: паралельний текст

Пошук за фіксованим рядком `function` із завданнями `1`, `2` та `4`. Для цього шаблону пул воркерів запускається лише за наявності понад `jobs * 4_000` файлів (див. [Паралельні воркери](https://greph.inline0.dev/uk/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. Порівняйте з `main` за допомогою процесу Benchmark, який запускається для запитів на злиття зі змінами в `src/`, `benchmarks/` або `bin/` та публікує порівняння поточної і базової версій у зведенні запуску.
5. Оновіть таблицю README після додавання нового тесту продуктивності до `main` під час запуску CI.

## Принципи продуктивності

Greph не намагається випередити ripgrep чи grep під час холодного сканування. Ripgrep реалізовано на Rust з оптимізованим вручну SIMD-скануванням літералів, і в опублікованих результатах і `rg`, і GNU `grep` швидші за Greph у кожному холодному текстовому скануванні. Цілі в них різні:

- Працювати достатньо швидко, щоб інтерактивне використання та цикли агентів відчувалися природно.
- Відповідати на повторні запити за прогрітими індексами: індексований пошук регулярних виразів, підрахунок і запити списку файлів швидші, ніж `rg` і `grep`, що сканують те саме дерево.
- Перевершувати `ast-grep` на індексованих і кешованих навантаженнях AST, де прогріті кеші Greph дають змогу не розбирати дерево повторно. Пошук AST без прогрівання кешу показує різні результати: `new $CLASS()` швидший за `sg`, а `array($$$ITEMS)` повільніший.
- Робити кожне покращення продуктивності вимірюваним і відтворюваним.

Заяви про продуктивність, не підтверджені звітом бенчмарку, не приймаються.
