Бенчмарки
В репозитории есть инструмент для бенчмарков в bin/ и benchmarks/. Он измеряет каждый режим поиска на реальных наборах данных (WordPress, Laravel) и созданных синтетических наборах, формирует структурированные отчеты и позволяет сравнивать серии отчетов.
Инструмент входит в репозиторий, а не в пакет Composer: поскольку 0.2.3, benchmarks/ и скрипты bin/bench* не включены в пакет, запускайте их из клона (git clone https://github.com/inline0/greph && cd greph && composer install).
Опубликованные результаты в README получены в запусках GitHub Actions, а не на локальных машинах. Локальные запуски полезны для итераций; эталонными считаются запуски CI.
Наборы данных
Синтетические наборы данных (synthetic-1k, synthetic-10k, synthetic-100k-single) создаются в benchmarks/corpora/synthetic/ при первом запуске. Реальные наборы данных не включены: разместите копию в benchmarks/corpora/wordpress или benchmarks/corpora/laravel (рабочий процесс CI клонирует WordPress/WordPress с помощью --depth=1). Наборы данных, для которых отсутствует каталог, пропускаются.
Запуск бенчмарков
# 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 (см. Параллельные рабочие процессы), а в наборе данных WordPress файлов меньше. Поэтому все три опубликованные строки выполняются в одном процессе и не демонстрируют масштабирование пула (#8).
Режим сканирования: AST
Нативный поиск по AST на типичных шаблонах:
new $CLASS()array($$$ITEMS)
Режим индексированного текста
Поиск по прогретому текстовому индексу с теми же шаблонами, что и в режиме сканирования. Включает запросы по буквальным строкам, без учета регистра, по целым словам, коротким токенам и регулярным выражениям.
Сводные запросы по индексу
Поиск по прогретому текстовому индексу с выводом количества результатов, файлов с совпадениями и файлов без совпадений. Эти запросы особенно выигрывают от хранилища списков вхождений, поскольку затраты на обработку каждого файла минимальны.
Индексированный / кэшированный AST
Поиск фактов в прогретом индексе AST и поиск по кэшированному AST на тех же шаблонах, что и в режиме сканирования AST.
Затраты на сборку
Затраты на построение с нуля триграммного индекса, индекса фактов AST и кэша AST. Полезно при выборе режима для конкретной нагрузки.
Как читать опубликованные результаты
README публикует снимок последнего запуска CI для каждого базового теста. Данные каждого раздела получены в конкретном запуске GitHub Actions и снабжены сведениями о наборе данных, среде выполнения, версии PHP, а также количестве измерений и прогревов. Чтобы воспроизвести результат, используйте ту же конфигурацию локально.
Сравнительные столбцы (rg, grep, sg) формируются в рамках одной задачи на одной среде выполнения и на одном наборе данных. Они не рассчитаны на основе внешних бенчмарков.
Как добавить бенчмарк
- Добавьте определение бенчмарка в
benchmarks/. - Добавьте соответствующий сценарий в набор регрессионных тестов, если аналогичного еще нет (чтобы также проверить измеряемое поведение).
- Запустите
./bin/bench --category <yours>, чтобы проверить новый бенчмарк. - Сравните результаты с
mainс помощью рабочего процесса Benchmark, который запускается для запросов на слияние, затрагивающихsrc/,benchmarks/илиbin/, и публикует сравнение текущей версии с базовой в сводке запуска. - Обновите таблицу 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)— медленнее. - Делать каждое улучшение производительности измеримым и воспроизводимым.
Заявления о производительности без отчета о бенчмарке не принимаются.