138 lines
8.6 KiB
Markdown
138 lines
8.6 KiB
Markdown
# Сборка и benchmark-методика
|
||
|
||
## Активная focused-постановка
|
||
|
||
Текущий benchmark отвечает на один практический вопрос: при каком `N` для
|
||
фиксированной малой доли правок становится выгодно переходить от contiguous
|
||
vector к tiered storage. Старую широкую матрицу типов, SIMD-профилей, leaf и
|
||
workload для этой калибровки не используют.
|
||
|
||
Все три кандидата имеют один и тот же тип данных и один и тот же flat hash:
|
||
|
||
| Имя в CSV | Реализация | Режим |
|
||
|---|---|---|
|
||
| `forced_vector_hash` | `AdaptiveSequence<uint32_t, true>` | принудительно vector |
|
||
| `forced_tiered_hash` | `AdaptiveSequence<uint32_t, true>` | принудительно tiered |
|
||
| `adaptive_hash` | `AdaptiveSequence<uint32_t, true>` | текущая resize-bound auto-policy |
|
||
|
||
Таким образом, поиск по значению не даёт одному кандидату скрытого преимущества:
|
||
стоимость хранения и обновления hash index присутствует у vector, tiered и
|
||
adaptive. Для forced tiered начальный leaf равен `ceil(sqrt(N))`. Auto-mode
|
||
выбирает mode и leaf только при capacity-boundary.
|
||
|
||
## Трасса
|
||
|
||
Mixed trace содержит ровно 100000 операций в default-запуске:
|
||
|
||
| Операция | Доля | Default count | Детали |
|
||
|---|---:|---:|---|
|
||
| индексное чтение | 97% | 97000 | случайный существующий индекс |
|
||
| hash find по значению | 1% | 1000 | `find_one`, 50% hit / 50% miss |
|
||
| вставка | 1% | 1000 | случайная позиция |
|
||
| удаление | 1% | 1000 | случайная существующая позиция |
|
||
|
||
Виды операций перемешиваются детерминированным seed. Вставки и удаления
|
||
сбалансированы, поэтому benchmark измеряет steady-size workload, но любая
|
||
реально достигнутая capacity-boundary и стоимость перехода остаются внутри
|
||
mixed timer. Построение исходного контейнера находится вне timer.
|
||
|
||
Кроме общей `mixed ops/s`, runner измеряет отдельные homogeneous batches и
|
||
выводит `read ops/s`, `find ops/s`, `insert ops/s`, `erase ops/s`. Быстрые read
|
||
и find batches содержат не менее 100000 вызовов для устойчивости таймера;
|
||
фактические batch counts записываются в CSV. Поэтому отдельные колонки — это
|
||
пропускная способность соответствующего типа операции, а не время его 1%-доли
|
||
в mixed trace.
|
||
|
||
Один и тот же материализованный trace и seed применяются к трём кандидатам.
|
||
Порядок кандидатов циклически меняется между paired repeats, чтобы фиксированная
|
||
первая или последняя позиция не принадлежала всегда одному представлению.
|
||
Checksum проверяет совпадение состояния и результатов операций.
|
||
|
||
## Capacity, leaf и hash во время измерения
|
||
|
||
Focused benchmark проверяет текущий контракт контейнера, а не внешнюю
|
||
эмуляцию:
|
||
|
||
- capacity увеличивается `x2`, когда очередная вставка не помещается;
|
||
- при `size <= capacity / 8` выполняется один shrink-шаг `capacity / 2`;
|
||
- mode и `leaf = ceil(sqrt(size))` пересчитываются только внутри этой
|
||
capacity-перестройки;
|
||
- focused cutoff auto-mode равен 4096;
|
||
- hash buckets рассчитываются из новой логической capacity с worst-case load
|
||
не выше 70% и не меняются независимо между capacity-boundaries.
|
||
|
||
Raw CSV сохраняет initial/final mode, leaf и logical capacity mixed-контейнера,
|
||
что позволяет увидеть включённый в mixed throughput переход `vector -> tiered`
|
||
или обратный переход. Для четырёх отдельных homogeneous batches поля
|
||
`read_mode`, `find_mode`, `insert_mode`, `erase_mode` и соответствующие
|
||
`*_leaf` отдельно фиксируют их фактический режим/геометрию; эти batches
|
||
стартуют с новых контейнеров и потому не обязаны повторять final mode/leaf
|
||
mixed-трассы.
|
||
|
||
## Воспроизводимый default-run
|
||
|
||
Из обычной командной строки Windows:
|
||
|
||
```bat
|
||
benchmark.bat
|
||
```
|
||
|
||
Скрипт выполняет ровно один focused-run:
|
||
|
||
1. `build.bat baseline test` — Release x64 `/O2`, `/MT`, без `/arch:AVX*` и
|
||
без IPO/LTO, затем correctness-тесты.
|
||
2. Создаёт `results\benchmarks\<timestamp>-focused\` и записывает metadata и
|
||
source/binary manifests.
|
||
3. Запускает `uc_focused_bench` для степеней двойки `N=256...65536`, 100000
|
||
mixed operations и 7 paired repeats.
|
||
4. Печатает таблицу медиан operations/second, сохраняет её в `summary.md`, а
|
||
raw repeat data — в `baseline-focused.csv`.
|
||
|
||
Эквивалентный вызов runner после сборки:
|
||
|
||
```bat
|
||
out\bin\baseline\Release\uc_focused_bench.exe --min-n 256 --max-n 65536 --operations 100000 --repeats 7 --output results\benchmarks\focused.csv
|
||
```
|
||
|
||
`--operations` должен быть положительным числом, кратным 100. Доступны также
|
||
`--seed`, `--min-n` и `--max-n`; границы диапазона округляются до степеней
|
||
двойки.
|
||
|
||
Финальную таблицу следует публиковать в каталоге соответствующего запуска в
|
||
`results/benchmarks/`. Документация хранит только постановку и подтверждённые
|
||
выводы, а не копию ещё незавершённой серии.
|
||
|
||
## CSV
|
||
|
||
Каждая raw-строка содержит:
|
||
|
||
- `profile`, `n`, `container`, `repeat`, `seed`;
|
||
- initial/final mixed `mode`, `leaf`, `logical_capacity` и отдельные mode/leaf
|
||
поля read/find/insert/erase batches;
|
||
- mixed counts, включая hit/miss hash find;
|
||
- реальные размеры отдельных read/find/insert/erase batches;
|
||
- `mixed_ops_per_sec`, `read_ops_per_sec`, `find_ops_per_sec`,
|
||
`insert_ops_per_sec`, `erase_ops_per_sec`;
|
||
- оценку allocated bytes и checksum.
|
||
|
||
Публикуемая таблица использует медиану семи повторов по каждой паре
|
||
`(N, container)`. Значения отдельных повторов не отбрасываются и остаются в
|
||
raw CSV.
|
||
|
||
## Historical / retired benchmark matrix
|
||
|
||
Старый `uc_bench`, вызовы `benchmark.bat smoke|quick|full`, multi-profile
|
||
сравнение `scalar/baseline/avx2`, типы от `uint32_t` до blob/string wrapper,
|
||
fixed leaf 64...1024, `std::deque`, `std::list`, phase traces и
|
||
`large_benchmark.bat` до N=100M относятся к **historical / retired** методике.
|
||
|
||
Их CSV сохранены для аудита истории проекта, но не участвуют в выборе текущего
|
||
cutoff: набор кандидатов, mix операций и наличие hash index отличаются от
|
||
focused постановки. Старые aggregate scores и speedup нельзя смешивать с новой
|
||
таблицей operations/second.
|
||
|
||
Профили `scalar` и `avx2` по-прежнему можно собирать для отдельных инженерных
|
||
экспериментов. `scalar` использует внутренний MSVC `/d2Qvec-` и не является
|
||
универсальной гарантией отсутствия SIMD в CRT/ABI; это ещё одна причина не
|
||
расширять текущий baseline-run до старой матрицы без отдельной задачи.
|