Files
UniversalContainer/results/benchmarks/20260811-213422-quick
Efim Beshmenev aea6e330e3 Realisation v1
2026-08-11 22:19:34 +03:00
..
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00
2026-08-11 22:19:34 +03:00

Quick-checkpoint 20260811-213422

Это итоговый engineering quick-checkpoint текущей итерации. Он фиксирует согласованную трёхпрофильную сборку, benchmark-матрицу и проверку адаптации, но не является full-size независимым holdout и не доказывает универсальное превосходство контейнера.

Происхождение серии

  • v14 (20260811-hysteresis-smoke-v14) проверил завершённый hysteresis на baseline smoke.
  • v15 (20260811-policy-quick-v15-hysteresis) проверил policy на baseline quick; moderate deferred стал лучшим из адаптивных вариантов этой серии.
  • этот run повторил полную quick-матрицу для scalar, baseline и avx2 и является основной точкой текущего handoff.

Среда и профили сборки

Среда сохранена в environment.json и environment.txt: AMD Ryzen 9 5900X, Windows 10 Pro 25H2, MSVC 19.51.36248.0 x64, CMake 4.3.1-msvc1, план питания Balanced. Во всех Release целях использованы /O2, статический runtime /MT, без IPO/LTO (/GL не использовался).

Профиль Существенные параметры
scalar /O2 /d2Qvec- /Qvec-report:1 /Oi-, без /arch:AVX*
baseline /O2, автовекторизация разрешена, без /arch:AVX*
avx2 /O2 /arch:AVX2, без vectorizer-disable флагов

/d2Qvec- — внутренний, не документированный публичным контрактом MSVC ключ. Здесь он означает проверенный на зафиксированной версии компилятора project-novec-профиль, но не гарантирует отсутствие всех SIMD-инструкций: x64 ABI, compiler runtime и CRT могут использовать базовый SSE2 или собственный dispatch.

Методика

benchmark.bat quick запускал профили последовательно в фиксированном порядке scalar -> baseline -> avx2. В каждом профиле suites выполнялись как tune -> adapt -> compare -> index:

  • quick использует 5 повторов;
  • tuning: размеры 10 000, 100 000 и 1 000 000;
  • comparison: размеры 1 000, 10 000, 100 000 и 1 000 000;
  • кандидаты одного повтора получают один и тот же заранее материализованный trace; стартовый кандидат циклически меняется между повторами;
  • analyzer проверяет согласованность checksum для сопоставимых успешных строк;
  • слишком дорогие комбинации deque/list могут получить skipped_cost_guard и не входят в соответствующую aggregate-ячейку.

Process affinity/pinning не задавались. Порядок профилей не рандомизировался, а план питания оставался Balanced. Поэтому результаты следует читать как инженерный quick-checkpoint, подверженный drift температуры, частоты и фоновой нагрузки, а не как окончательную публикационную оценку.

std::deque и std::list здесь только внешние фиксированные baselines. Они никогда не являются внутренними режимами AdaptiveSequence; у list измеряется индексная семантика с линейным проходом.

Проверка адаптации

Финальный запуск валидатора прошёл:

  • 282 compare-ячейки;
  • 48 adapt-ячеек.

Текстовый итог повторной проверки сохранён в validation.txt. Для всех suites дополнительно проверены результаты одинаковых трасс: расхождений checksum внутри профиля и между scalar/baseline/avx2 нет. Полнота raw матрицы: по 1125 строк tune, 800 adapt, 4700 compare и 270 index на профиль; в compare по 225 строк на профиль имеют ожидаемый skipped_cost_guard, остальные статусы — ok.

Для короткого negative control допускаются ноль переключений и ноль leaf-rebuilds; для stationary default — не более одного. У явно двухфазной трассы phase_10_uniform_10_local_80_read есть две разные edit-фазы. Первоначальный лимит одной leaf-rebuild ошибочно трактовал их как одну фазу; лимит был исправлен до двух только для этой структуры. Измерительные CSV не менялись, и после исправления спецификации валидатор прошёл весь набор. Этот pass доказывает ограниченность transition churn на проверяемых трассах, но сам по себе не доказывает оптимальную производительность policy.

Проверка выполняется по медианам пяти повторов. В raw compare есть один seed-specific случай phase_uniform_local_read, N=1M с тремя leaf-rebuilds; медиана этой ячейки равна двум. Это не stationary churn, но показывает, что следующий holdout должен валидировать не только медианы, а каждый повтор.

Основные результаты

В aggregate-compare.csv score каждой ячейки нормирован по лучшему фиксированному baseline в этой ячейке; выше — лучше.

Кандидат Overall score Eligible cells
forced tiered, leaf64 0.395052 282
forced tiered, leaf128 0.391598 282
adaptive deferred 0.347315 282
adaptive eager 0.326839 282
reserved vector 0.146329 282
external deque 0.080267 267
external list-index 0.012763 162

adaptive deferred превосходит reserved vector в aggregate этой конкретной quick-матрицы, но проигрывает лучшим forced leaf-кандидатам. Победа над лучшим фиксированным oracle или над всеми структурами не доказана.

В терминах именно aggregate score adaptive выше reserved vector в 2.37 раза, но ниже leaf64 на 12.1% и leaf128 на 11.3%. Это отношения иерархически агрегированных нормированных score, а не прямые коэффициенты ускорения времени. Прямое парное агрегирование времени даёт ту же картину: adaptive быстрее vector примерно в 2.37 раза, но медленнее leaf64 на 13.74% и leaf128 на 12.75%; leaf256 он уже опережает на 1.07%. После hysteresis stationary-ячейки имеют не более одного storage switch и одной leaf-rebuild; два переключения/две rebuild встречаются только там, где trace явно содержит burst или две разные edit-фазы. Directory-only rebuild в выбранной policy в этом run не потребовался.

Главный оставшийся regret — не повторные переключения, а cold adaptation. Для blob64 и non-trivial string при N=100k policy делает один переход без rebuild, но до него успевает выполнить дорогие O(N) vector edits и затем платит за конвертацию; против заранее подготовленного leaf64 это в среднем примерно 2.45x и 4.03x медленнее соответственно. Есть и противоположная слепая зона: read_99, N=1M остаётся vector из-за 5% entry threshold, хотя редкие edits уже достаточно дороги, чтобы fixed tiered выиграл. Следующий вариант policy должен использовать накопленный regret/стоимость edit, а не только их долю.

В aggregate-adapt.csv лучшие fixed варианты — leaf128 (0.817859) и leaf256 (0.788496); лучший адаптивный policy moderate deferred получил 0.216999. Adapt-сценарии остаются главным источником regret. При этом на длинной exact phase moderate примерно в 11.1 раза быстрее vector, но всё ещё в 5.27 раза медленнее заранее tiered oracle; на коротком negative control ложных переходов нет, а цена сбора статистики составляет около 8.5%.

Tuning выбрал leaf128 как сильнейший quick-кандидат во всех трёх профилях:

Профиль Лучшие параметры Score
scalar leaf128, levels4 0.878968
baseline leaf128, levels3 0.873461
avx2 leaf128, levels3 0.887906

Это выбор для измеренной матрицы, а не универсальная константа. Index-suite также показал большой выигрыш специализированного flat hash index над линейным lookup vector, но только в lookup-подзадаче и ценой дополнительной памяти; переносить этот вывод на контейнер целиком нельзя.

Лучший единый tuning-компромисс трёх профилей — leaf=128, fanout=64, levels=3; вариант с levels=4 отстал по cross-profile score всего на 0.276%, поэтому точную глубину пока нельзя считать надёжно определённой. Leaf, напротив, устойчивее: 14 из 15 логических tuning-ячеек выбрали одинаковый leaf во всех профилях. Random access всегда предпочёл 1024, большинство edit/mixed-ячеек — 64, а localized edit при N=1M — 128.

AVX2 не дал общего выигрыша для контейнерного mix: для tuning-конфига 128/64/3 AVX2 и baseline различались лишь на 0.26% по cellwise geometric mean. На compare AVX2 ускорил reserved vector примерно на 8.9%, но fixed tiered — только на 23%, а adaptive deferred оказался на 0.9% медленнее baseline. Порядок профилей не рандомизирован, поэтому проценты следует считать инженерным сигналом, а не изолированным доказательством эффекта SIMD.

Отдельно отмечен устойчивый codegen outlier: AVX2 adaptive-deferred sequential uint32 во всех четырёх N оказался в 1.85–1.98 раза медленнее baseline во всех пяти повторах, при совпадающих checksums. До профилирования generated code это нельзя объяснять как общий недостаток AVX2 или как шум одной выборки.

Hash index выиграл у linear lookup во всех 27 проверенных index-ячейках, но его геометрическое среднее потребление памяти составило 9.26x от payload vector (диапазон 7.00x–17.49x). Экстремальные коэффициенты скорости неустойчивы: при N=1M выполнялось только 50 запросов, построение индекса не входило в таймер, а свежепостроенный hash был cache-hot. Поэтому этот suite подтверждает пользу опционального индекса качественно, но не является точной оценкой production ускорения.

Артефакты и provenance

  • *-raw.csv — отдельные измерения;
  • *-summary.csv — summary внутри профиля;
  • aggregate-*.csv и cell-medians-*.csv — объединённые результаты;
  • environment.json / environment.txt — машина, toolchain, флаги и порядок профилей;
  • source-manifest.sha256 — 23 файла workspace на момент запуска;
  • binary-manifest.sha256 — 9 измерявшихся EXE (uc_demo, uc_tests, uc_bench для трёх профилей).

В metadata нет Git HEAD, а workspace на момент запуска имел 12 dirty entries, поэтому manifests — основной источник provenance. Они являются неизменяемым снимком именно момента измерения. После run были дополнены docs/findings.md и исправлена только спецификация лимита в tools/validate_adaptation.ps1; это два текущих расхождения с source manifest. C++-исходники и все девять Release EXE по-прежнему совпадают со снимком. Манифесты намеренно не пересоздаются задним числом.

Ограничения

  • это quick с пятью повторами, не full и не независимый multi-seed holdout;
  • нет pinning/affinity, фиксированного high-performance power plan и рандомизированного порядка профилей;
  • segmented backend пока одноуровневый prototype, а не завершённая многоуровневая структура;
  • policy всё ещё заметно уступает лучшему fixed leaf oracle на adapt workloads;
  • память учитывается в benchmark, но для окончательного вывода нужен отдельный контролируемый memory-budget experiment;
  • deque/list — внешние baselines с cost-guard пропусками, а не альтернативные режимы адаптивного контейнера.