Files
2026-08-13 23:42:26 +03:00

8.6 KiB
Raw Permalink Blame History

Сборка и 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:

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 после сборки:

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 до старой матрицы без отдельной задачи.