
# Бенчмаркове

Хранилището включва система за бенчмаркове в `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/bg/docs/advanced/parallel)), повече от броя на файловете в корпуса WordPress, така че и трите публикувани реда се изпълняват в един процес и не показват мащабиране на пула ([#8](https://github.com/inline0/greph/issues/8)).

### Режим на сканиране: AST

Нативно търсене в AST по представителни шаблони:

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

### Режим на индексиран текст

Търсене в затоплен текстов индекс със същите шаблони като при режима на сканиране. Включва заявки за буквално търсене, без разлика между главни и малки букви, цели думи, кратки токени и регулярни изрази.

### Заявки за обобщения в индекса

Търсене в затоплен текстов индекс с изходи за брой, файлове със съвпадения и файлове без съвпадения. Те се възползват най-много от хранилището с postings, защото обработката на файл е най-евтина.

### Индексиран / кеширан 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, след като изпълнението на CI, включващо новия бенчмарк, бъде включено в `main`.

## Философия за производителността

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

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

Не се приемат твърдения за производителност без подкрепа от отчет на бенчмарк.
