Перейти к содержимому

Бенчмарки

В репозитории есть инструмент для бенчмарков в 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) формируются в рамках одной задачи на одной среде выполнения и на одном наборе данных. Они не рассчитаны на основе внешних бенчмарков.

Как добавить бенчмарк

  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) — медленнее.
  • Делать каждое улучшение производительности измеримым и воспроизводимым.

Заявления о производительности без отчета о бенчмарке не принимаются.